diff --git a/.classpath b/.classpath
index 002ad57..2a83b68 100644
--- a/.classpath
+++ b/.classpath
@@ -34,5 +34,6 @@
+
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..2b978b3
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,38 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: bug
+assignees: CyB3RC0nN0R, delvh, DieGurke, derharry333
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Desktop (please complete the following information):**
+ - OS: [e.g. iOS]
+ - Browser [e.g. chrome, safari]
+ - Version [e.g. 22]
+
+**Smartphone (please complete the following information):**
+ - Device: [e.g. iPhone6]
+ - OS: [e.g. iOS8.1]
+ - Browser [e.g. stock browser, safari]
+ - Version [e.g. 22]
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..fbdebf6
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: enhancement
+assignees: CyB3RC0nN0R, delvh, DieGurke
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.github/PULL_REQUEST_TEMPLATE/bugfix.md b/.github/PULL_REQUEST_TEMPLATE/bugfix.md
new file mode 100644
index 0000000..e189f31
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/bugfix.md
@@ -0,0 +1,10 @@
+---
+name: Bug fix
+title: Fixed Bug
+labels: bug
+assignees: CyB3RC0nN0R, delvh, DieGurke
+reviewers: CyB3RC0nN0R, delvh
+projects: Envoy
+milestone: Envoy v0.3-alpha
+---
+Fixes #{issue}
diff --git a/.github/PULL_REQUEST_TEMPLATE/feature_integration.md b/.github/PULL_REQUEST_TEMPLATE/feature_integration.md
new file mode 100644
index 0000000..945e7d3
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/feature_integration.md
@@ -0,0 +1,9 @@
+---
+name: Feature integration
+title: Added feature
+labels: enhancement
+assignees: CyB3RC0nN0R, delvh, DieGurke
+reviewers: CyB3RC0nN0R, delvh
+projects: Envoy
+milestone: Envoy v0.3-alpha
+---
diff --git a/.github/PULL_REQUEST_TEMPLATE/javadoc_upgrade.md b/.github/PULL_REQUEST_TEMPLATE/javadoc_upgrade.md
new file mode 100644
index 0000000..7f1786d
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/javadoc_upgrade.md
@@ -0,0 +1,9 @@
+---
+name: Updated Javadoc
+title: Updated Javadoc
+labels: documentation
+assignees: CyB3RC0nN0R, delvh
+reviewers: CyB3RC0nN0R, delvh
+projects: Envoy
+milestone: Envoy v0.3-alpha
+---
diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs
index 7103be7..269827f 100644
--- a/.settings/org.eclipse.jdt.ui.prefs
+++ b/.settings/org.eclipse.jdt.ui.prefs
@@ -1,2 +1,3 @@
eclipse.preferences.version=1
-org.eclipse.jdt.ui.text.custom_code_templates=
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.text.custom_code_templates=/**\r\n * @return the ${bare_field_name}\r\n * @since Envoy Server Standalone v0.1-alpha\r\n *//**\r\n * @param ${param} the ${bare_field_name} to set\r\n * @since Envoy Server Standalone v0.1-alpha\r\n *//**\r\n * Creates an instance of @link{${enclosing_type}}.\r\n *\r\n * ${tags}\r\n * @since Envoy Server Standalone v0.1-alpha\r\n *//**\r\n * Project\: <strong>${project_name}</strong><br>\r\n * File\: <strong>${file_name}</strong><br>\r\n * Created\: <strong>${date}</strong><br>\r\n * \r\n * @author ${user}\r\n * @since Envoy Server Standalone v0.1-alpha\r\n *//**\r\n * ${tags}\r\n * @since Envoy Server Standalone v0.1-alpha\r\n *//**\r\n * @author ${user}\r\n *\r\n * ${tags}\r\n * @since Envoy Server Standalone v0.1-alpha\r\n *//**\r\n * ${tags}\r\n * ${see_to_target}\r\n * @since Envoy Server Standalone v0.1-alpha\r\n */${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}\r\n\r\n\r\n\r\n${exception_var}.printStackTrace();${body_statement}\r\n${body_statement}\r\nreturn ${field};${field} \= ${param};
diff --git a/pom.xml b/pom.xml
index b85a456..5b81ded 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,6 +28,11 @@
java-nio-server
0.0.1-SNAPSHOT
+
+ org.hibernate
+ hibernate-core
+ 5.4.10.Final
+
diff --git a/src/main/java/envoy/server/data/Message.java b/src/main/java/envoy/server/data/Message.java
new file mode 100644
index 0000000..19e25a6
--- /dev/null
+++ b/src/main/java/envoy/server/data/Message.java
@@ -0,0 +1,194 @@
+package envoy.server.data;
+
+import java.util.Date;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+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.
+ *
+ * Project: envoy-server-standalone
+ * File: Message.java
+ * Created: 02.01.2020
+ *
+ * @author Kai S. K. Engelbart
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+@Entity
+@Table(name = "messages")
+@NamedQueries(
+ { @NamedQuery(query = "SELECT m FROM Message m WHERE m.recipient =:recipient AND m.state = 1", name = "getUnreadMessages"), @NamedQuery(
+ query = "SELECT m FROM Message m WHERE m.sender =:sender AND m.state = :state",
+ name = "find read messages"//TODO do we need this namedQuery?
+ ), @NamedQuery(query = "SELECT m FROM Message m WHERE m.id = :messageId", name = "get message") }//TODO do we need this namedQuery?
+)
+public class Message {
+
+ @Id
+ private long id;
+ private User sender, recipient;
+ @Temporal(TemporalType.TIMESTAMP)
+ private Date creationDate;
+ @Temporal(TemporalType.TIMESTAMP)
+ private Date receivedDate;
+ @Temporal(TemporalType.TIMESTAMP)
+ private Date readDate;
+ private envoy.data.Message.MessageStatus status;
+ private String text;
+ private byte[] attachment;
+
+ /**
+ * The constructor for a database object
+ *
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public Message() {}
+
+ // TODO: everything except ID
+ /**
+ * @param message the {@link envoy.data.Message} to convert into a database
+ * {@link Message}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public Message(envoy.data.Message message) {
+ id = message.getId();
+ status = message.getStatus();
+ text = message.getText();
+ }
+
+ /**
+ * @return a database {@link Message} converted into an
+ * {@link envoy.data.Message}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public envoy.data.Message toCommonMessage() {
+ // TODO: Attachment, dates
+ return new MessageBuilder(sender.getId(), recipient.getId()).setText(text).setDate(creationDate).setStatus(status).build();
+ }
+
+ /**
+ * @return the id of a {link envoy.data.Message}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public long getId() { return id; }
+
+ /**
+ * @param id the id to set
+ * @since Envoy Server Standalone v0.1-alpha
+ * @see Message#getId()
+ */
+ public void setId(long id) { this.id = id; }
+
+ /**
+ * @return the sender of a {link envoy.data.Message}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public User getSender() { return sender; }
+
+ /**
+ * @param sender the sender to set
+ * @since Envoy Server Standalone v0.1-alpha
+ * @see Message#getSender()
+ */
+ public void setSender(User sender) { this.sender = sender; }
+
+ /**
+ * @return the recipient of a {link envoy.data.Message}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public User getRecipient() { return recipient; }
+
+ /**
+ * @param recipient the recipient to set
+ * @since Envoy Server Standalone v0.1-alpha
+ * @see Message#getRecipient()
+ */
+ public void setRecipient(User recipient) { this.recipient = recipient; }
+
+ /**
+ * @return the date at which a {link envoy.data.Message} has been created
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public Date getCreationDate() { return creationDate; }
+
+ /**
+ * @param creationDate the creation date to set
+ * @since Envoy Server Standalone v0.1-alpha
+ * @see Message#getCreationDate()
+ */
+ public void setCreationDate(Date creationDate) { this.creationDate = creationDate; }
+
+ /**
+ * @return the date at which a {link envoy.data.Message} has been received by
+ * the server
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public Date getReceivedDate() { return receivedDate; }
+
+ /**
+ * @param receivedDate the received date to set
+ * @since Envoy Server Standalone v0.1-alpha
+ * @see Message#getReceivedDate()
+ */
+ public void setReceivedDate(Date receivedDate) { this.receivedDate = receivedDate; }
+
+ /**
+ * @return the date at which a {link envoy.data.Message} has been read
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public Date getReadDate() { return readDate; }
+
+ /**
+ * @param readDate the read date to set
+ * @since Envoy Server Standalone v0.1-alpha
+ * @see Message#getReadDate()
+ */
+ public void setReadDate(Date readDate) { this.readDate = readDate; }
+
+ /**
+ * @return the status of a {link envoy.data.Message}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public envoy.data.Message.MessageStatus getStatus() { return status; }
+
+ /**
+ * @param status the new status of a {link envoy.data.Message}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public void setStatus(envoy.data.Message.MessageStatus status) { this.status = status; }
+
+ /**
+ * @return the text content of a {link envoy.data.Message}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public String getText() { return text; }
+
+ /**
+ * @param text the new text content of a {@link envoy.data.Message}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public void setText(String text) { this.text = text; }
+
+ /**
+ * @return the attachment of a {@link envoy.data.Message}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public byte[] getAttachment() { return attachment; }
+
+ /**
+ * @param attachment the new attachment
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public void setAttachment(byte[] attachment) { this.attachment = attachment; }
+}
diff --git a/src/main/java/envoy/server/data/User.java b/src/main/java/envoy/server/data/User.java
new file mode 100644
index 0000000..e0de15f
--- /dev/null
+++ b/src/main/java/envoy/server/data/User.java
@@ -0,0 +1,120 @@
+package envoy.server.data;
+
+import java.util.Date;
+import java.util.List;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQuery;
+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
+ * without bringing the dependency of JPA/Hibernate into the client.
+ * It will be referenced as "database user" to clarify between the different
+ * user objects.
+ *
+ * Project: envoy-server-standalone
+ * File: User.java
+ * Created: 02.01.2020
+ *
+ * @author Kai S. K. Engelbart
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+@Entity
+@Table(name = "users")
+@NamedQuery(query = "SELECT u FROM DBUser u WHERE u.id = :id", name = "getUserById")
+public class User {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+ private String name;
+ private byte[] passwordHash;
+ @Temporal(TemporalType.TIMESTAMP)
+ private Date lastSeen;
+ private envoy.data.User.UserStatus status;
+ private List contacts;
+
+ /**
+ * @return the id of a {link envoy.data.User}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public long getId() { return id; }
+
+ /**
+ * @param id the id to set
+ * @since Envoy Server Standalone v0.1-alpha
+ * @see User#getId
+ */
+ public void setId(long id) { this.id = id; }
+
+ /**
+ * @return the name of a {link envoy.data.User}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public String getName() { return name; }
+
+ /**
+ * @param name the username to set
+ * @since Envoy Server Standalone v0.1-alpha
+ * @see User#getName()
+ */
+ public void setName(String name) { this.name = name; }
+
+ /**
+ * @return the passwordHash of a {link envoy.data.User}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public byte[] getPasswordHash() { return passwordHash; }
+
+ /**
+ * @param passwordHash the password hash to set
+ * @since Envoy Server Standalone v0.1-alpha
+ * @see User#getPasswordHash()
+ */
+ public void setPasswordHash(byte[] passwordHash) { this.passwordHash = passwordHash; }
+
+ /**
+ * @return the last date an {link envoy.data.User} has been online
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public Date getLastSeen() { return lastSeen; }
+
+ /**
+ * @param lastSeen the latest date at which has been seen to set
+ * @since Envoy Server Standalone v0.1-alpha
+ * @see User#getLastSeen()
+ */
+ public void setLastSeen(Date lastSeen) { this.lastSeen = lastSeen; }
+
+ /**
+ * @return the status of a {link envoy.data.User}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public envoy.data.User.UserStatus getStatus() { return status; }
+
+ /**
+ * @param status the status to set
+ * @since Envoy Server Standalone v0.1-alpha
+ * @see User#getStatus()
+ */
+ public void setStatus(envoy.data.User.UserStatus status) { this.status = status; }
+
+ /**
+ * @return the contacts of a {link envoy.data.User}
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public List getContacts() { return contacts; }
+
+ /**
+ * @param contacts the contacts to set
+ * @since Envoy Server Standalone v0.1-alpha
+ * @see User#getContacts()
+ */
+ public void setContacts(List contacts) { this.contacts = contacts; }
+}
diff --git a/src/main/java/envoy/server/database/PersistenceManager.java b/src/main/java/envoy/server/database/PersistenceManager.java
new file mode 100644
index 0000000..e7c2dc8
--- /dev/null
+++ b/src/main/java/envoy/server/database/PersistenceManager.java
@@ -0,0 +1,78 @@
+package envoy.server.database;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Persistence;
+
+import org.hibernate.Session;
+
+import envoy.server.data.Message;
+import envoy.server.data.User;
+
+/**
+ * Project: envoy-server-standalone
+ * File: PersistenceManager.java
+ * Created: 1 Jan 2020
+ *
+ * @author Leon Hofmeister
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+public class PersistenceManager {
+
+ private EntityManager entityManager = Persistence.createEntityManagerFactory("envoy").createEntityManager();
+
+ /**
+ * Adds a {@link User} to the database.
+ *
+ * @param User the {@link User} to add to the database
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public void addUser(User User) { entityManager.persist(User); }
+
+ /**
+ * 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) { entityManager.persist(message); }
+
+ /**
+ * Updates a {@link User} in the database
+ *
+ * @param user the {@link User} to add to the database
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public void updateUser(User user) { entityManager.unwrap(Session.class).merge(user); }
+
+ /**
+ * 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) { entityManager.unwrap(Session.class).merge(message); }
+
+ /**
+ * Searches for a user with a specific id.
+ *
+ * @param id - the id to search for
+ * @return the user with the specified id
+ * @since Envoy Server Standalone v0.1-alpha
+ */
+ public User getUserById(long id) { return (User) entityManager.createNamedQuery("getUserById").setParameter("id", id).getSingleResult(); }
+
+ /**
+ * Returns all messages received while being offline.
+ *
+ * @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
+ */
+ @SuppressWarnings("unchecked")
+ public List getUnreadMessages(User user) {
+ // TODO may need to be changed to clientId
+ return entityManager.createNamedQuery("getUnreadMessages").setParameter("recipient", user).getResultList();
+ }
+}
\ No newline at end of file