diff --git a/src/main/java/envoy/data/LoginCredentials.java b/src/main/java/envoy/data/LoginCredentials.java
index 86b166c..58d14d4 100644
--- a/src/main/java/envoy/data/LoginCredentials.java
+++ b/src/main/java/envoy/data/LoginCredentials.java
@@ -6,10 +6,12 @@ import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
/**
+ * Contains a {@link User}'s login information.
+ *
* Project: envoy-common
* File: LoginCredentials.java
* Created: 29.12.2019
- *
+ *
* @author Kai S. K. Engelbart
* @since Envoy Common v0.2-alpha
*/
@@ -22,27 +24,18 @@ public class LoginCredentials implements Serializable {
/**
* Creates an in stance of {@link LoginCredentials}.
- *
+ *
* @param name the name of the user
* @param password the password of the user (will be converted to a hash)
- * @throws NoSuchAlgorithmException
+ * @throws NoSuchAlgorithmException if the algorithm used is unknown
+ * @since Envoy Common v0.2-alpha
*/
public LoginCredentials(String name, char[] password) throws NoSuchAlgorithmException {
this.name = name;
passwordHash = getSha256(toByteArray(password));
}
- @Override
- public String toString() {
- Formatter form = new Formatter();
- form.format("LoginCredentials[name=%s,passwordHash=", name);
- for (int i = 0; i < passwordHash.length; i++)
- form.format("%02x", passwordHash[i]);
- form.format("]");
- String str = form.toString();
- form.close();
- return str;
- }
+ private byte[] getSha256(byte[] input) throws NoSuchAlgorithmException { return MessageDigest.getInstance("SHA-256").digest(input); }
private byte[] toByteArray(char[] chars) {
byte[] bytes = new byte[chars.length * 2];
@@ -53,9 +46,14 @@ public class LoginCredentials implements Serializable {
return bytes;
}
- private byte[] getSha256(byte[] input) throws NoSuchAlgorithmException {
- MessageDigest md = MessageDigest.getInstance("SHA-256");
- return md.digest(input);
+ @Override
+ public String toString() {
+ try (Formatter form = new Formatter()) {
+ form.format("LoginCredentials[name=%s,passwordHash=", name);
+ for (byte element : passwordHash)
+ form.format("%02x", element);
+ return form.format("]").toString();
+ }
}
/**
diff --git a/src/main/java/envoy/data/Message.java b/src/main/java/envoy/data/Message.java
index 555c751..ddbfba2 100644
--- a/src/main/java/envoy/data/Message.java
+++ b/src/main/java/envoy/data/Message.java
@@ -1,6 +1,7 @@
package envoy.data;
import java.io.Serializable;
+import java.text.SimpleDateFormat;
import java.util.Date;
/**
@@ -11,36 +12,107 @@ import java.util.Date;
* Project: envoy-common
* File: Message.java
* Created: 28.12.2019
- *
+ *
* @author Kai S. K. Engelbart
+ * @author Leon Hofmeister
* @since Envoy Common v0.2-alpha
*/
-public abstract class Message implements Serializable {
+public class Message implements Serializable {
- private final long id;
- private final User sender, recipient;
- private final Date date;
+ /**
+ * This enumeration defines all possible statuses a {link Message} can have.
+ *
+ * @since Envoy Common v0.2-alpha
+ */
+ public static enum MessageStatus {
+
+ /**
+ * is selected, if a message was sent but not received by the server yet.
+ */
+ WAITING,
+
+ /**
+ * is selected, if a sent message was received by the server.
+ */
+ SENT,
+
+ /**
+ * is selected, if a message was delivered from the server to the recipient, but
+ * has not been read yet.
+ */
+ RECEIVED,
+
+ /**
+ * is selected, if a recipient opened the corresponding chat of said message.
+ */
+ READ
+ }
+
+ private final long id, senderId, recipientId;
+ private final transient User sender, recipient;
+ private final Date date;
+ private final String text;
+ private final MessageAttachment> attachment;
private MessageStatus status;
private static final long serialVersionUID = -4393477412979594435L;
/**
- * Initializes a {@link Message} from the client's perspective. The current date
- * is used as the message date and the status is set to
- * {@link MessageStatus#WAITING}.
- *
- * @param id unique ID
- * @param sender the user who sends the message
- * @param recipient the user who receives the message
+ * Initializes a {@link Message} with values for all of its properties. The use
+ * of this constructor is only intended for the {@link MessageBuilder} class, as
+ * this class provides {@code null} checks and default values for all
+ * properties.
+ *
+ * @param id unique ID
+ * @param sender the user who sends the message
+ * @param recipient the user who receives the message
+ * @param date the creation date of the message
+ * @param text the text content of the message
+ * @param attachment the attachment of the message, if present
+ * @param status the current {@link MessageStatus} of the message
* @since Envoy Common v0.2-alpha
*/
- public Message(long id, User sender, User recipient) {
+ Message(long id, User sender, User recipient, Date date, String text, MessageAttachment> attachment, MessageStatus status) {
this.id = id;
this.sender = sender;
this.recipient = recipient;
- date = new Date();
- status = MessageStatus.WAITING;
+ this.date = date;
+ this.text = text;
+ this.attachment = attachment;
+ this.status = status;
+
+ senderId = sender.getId();
+ recipientId = recipient.getId();
+ }
+
+ /**
+ * Changes the current {@link MessageStatus} to the next logical status.
+ *
+ * The underlying order is as follows:
+ *
+ * - {@link MessageStatus#WAITING}
+ *
- {@link MessageStatus#SENT}
+ *
- {@link MessageStatus#RECEIVED}
+ *
- {@link MessageStatus#READ}
+ *
+ *
+ * @since Envoy Common v0.2-alpha
+ */
+ public void nextStatus() {
+ if (status == MessageStatus.READ) throw new IllegalStateException("Message status READ is already reached");
+ status = MessageStatus.values()[status.ordinal() + 1];
+ }
+
+ @Override
+ public String toString() {
+ return String.format("TextMessage[id=%d,sender=%s,recipient=%s,date=%s,status=%s,text=%s]",
+ id,
+ sender,
+ recipient,
+ new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(date),
+ status,
+ text);
}
/**
@@ -55,43 +127,45 @@ public abstract class Message implements Serializable {
*/
public User getSender() { return sender; }
+ /**
+ * @return the sender ID of this message
+ * @since Envoy Common v0.2-alpha
+ */
+ public long getSenderId() { return senderId; }
+
/**
* @return the recipient of this message
* @since Envoy Common v0.2-alpha
*/
public User getRecipient() { return recipient; }
+ /**
+ * @return the recipient ID of this message
+ * @since Envoy Common v0.2-alpha
+ */
+ public long getRecipientId() { return recipientId; }
+
/**
* @return the date at which this message was created
* @since Envoy Common v0.2-alpha
*/
public Date getDate() { return date; }
+ /**
+ * @return the text content of this message
+ * @since Envoy Common v0.2-alpha
+ */
+ public String getText() { return text; }
+
+ /**
+ * @return the messageAttachment
+ * @since Envoy Common v0.2-alpha
+ */
+ public MessageAttachment> getAttachment() { return attachment; }
+
/**
* @return the current status of this message
* @since Envoy Common v0.2-alpha
*/
public MessageStatus getStatus() { return status; }
-
- /**
- * Changes the current {@link MessageStatus} to the next logical status.
- *
- * The underlying order is as follows:
- *
- * - {@link MessageStatus#WAITING}
- *
- {@link MessageStatus#SENT}
- *
- {@link MessageStatus#RECEIVED}
- *
- {@link MessageStatus#READ}
- *
- *
- * @since Envoy Common v0.2-alpha
- */
- public void nextStatus() {
- if (status == MessageStatus.READ) throw new IllegalStateException("Message status READ is already reached");
- status = MessageStatus.values()[status.ordinal() + 1];
- }
-
- public static enum MessageStatus {
- WAITING, SENT, RECEIVED, READ
- }
}
\ No newline at end of file
diff --git a/src/main/java/envoy/data/MessageAttachment.java b/src/main/java/envoy/data/MessageAttachment.java
new file mode 100644
index 0000000..ee4db64
--- /dev/null
+++ b/src/main/java/envoy/data/MessageAttachment.java
@@ -0,0 +1,24 @@
+package envoy.data;
+
+import java.io.Serializable;
+
+/**
+ * This interface should be used for any type supposed to be a {@link Message}
+ * attachment (i.e. images or sound).
+ *
+ * Project: envoy-common
+ * File: MessageAttachment.java
+ * Created: 30 Dec 2019
+ *
+ * @author Leon Hofmeister
+ * @param the type of this message attachment
+ * @since Envoy Common v0.2-alpha
+ */
+public interface MessageAttachment extends Serializable {
+
+ /**
+ * @return the type implementing this interface
+ * @since Envoy Common v0.2-alpha
+ */
+ T get();
+}
diff --git a/src/main/java/envoy/data/MessageBuilder.java b/src/main/java/envoy/data/MessageBuilder.java
new file mode 100644
index 0000000..4217663
--- /dev/null
+++ b/src/main/java/envoy/data/MessageBuilder.java
@@ -0,0 +1,125 @@
+package envoy.data;
+
+import java.util.Date;
+
+import envoy.data.Message.MessageStatus;
+
+/**
+ * Provides a method of constructing the {@link Message} class.
+ *
+ * Project: envoy-common
+ * File: MessageBuilder.java
+ * Created: 31.12.2019
+ *
+ * @author Kai S. K. Engelbart
+ * @since Envoy Common v0.2-alpha
+ */
+public class MessageBuilder {
+
+ // Mandatory properties without default values
+ private final User sender, recipient;
+
+ // Properties with default values
+ private long id;
+ private Date date;
+ private String text;
+ private MessageAttachment> attachment;
+ private Message.MessageStatus status;
+
+ /**
+ * Creates an instance of {@link MessageBuilder} with all mandatory values
+ * without defaults for the {@link Message} class.
+ *
+ * @param sender the user who sends the {@link Message}
+ * @param recipient the user who received the {@link Message}
+ * @since Envoy Common v0.2-alpha
+ */
+ public MessageBuilder(User sender, User recipient) {
+ if (sender == null) throw new NullPointerException("Message sender is null");
+ if (recipient == null) throw new NullPointerException("Message recipient is null");
+ this.sender = sender;
+ this.recipient = recipient;
+ }
+
+ /**
+ * Creates an instance of {@link Message} with the previously supplied values.
+ * If a mandatory value is not set, a default value will be used instead:
+ *
+ *
+ *
+ * {@code date} |
+ * {@code new Date()} |
+ *
+ *
+ * {@code text} |
+ * {@code ""} |
+ *
+ *
+ * {@code status} |
+ * {@code MessageStatus.WAITING} |
+ *
+ *
+ *
+ * @return a new instance of {@link Message}
+ * @since Envoy Common v0.2-alpha
+ */
+ public Message build() {
+ // Supplement default values
+ if (date == null) date = new Date();
+ if (text == null) text = "";
+ if (status == null) status = MessageStatus.WAITING;
+
+ return new Message(id, sender, recipient, date, text, attachment, status);
+ }
+
+ /**
+ * @param id the unique ID of the {@link Message} to create
+ * @return this {@link MessageBuilder}
+ * @since Envoy Common v0.2-alpha
+ */
+ public MessageBuilder setId(long id) {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * @param date the creation date of the {@link Message} to create
+ * @return this {@link MessageBuilder}
+ * @since Envoy Common v0.2-alpha
+ */
+ public MessageBuilder setDate(Date date) {
+ this.date = date;
+ return this;
+ }
+
+ /**
+ * @param text the text of the {@link Message} to create
+ * @return this {@link MessageBuilder}
+ * @since Envoy Common v0.2-alpha
+ */
+ public MessageBuilder setText(String text) {
+ this.text = text;
+ return this;
+ }
+
+ /**
+ * @param attachment the {@link MessageAttachment} of the {@link Message} to
+ * create
+ * @return this {@link MessageBuilder}
+ * @since Envoy Common v0.2-alpha
+ */
+ public MessageBuilder setAttachment(MessageAttachment> attachment) {
+ this.attachment = attachment;
+ return this;
+ }
+
+ /**
+ * @param status the {@link MessageStatus} of the {@link Message} to create
+ * @return this {@link MessageBuilder}
+ * @since Envoy Common v0.2-alpha
+ */
+ public MessageBuilder setStatus(Message.MessageStatus status) {
+ this.status = status;
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/envoy/data/MessageIdGenerator.java b/src/main/java/envoy/data/MessageIdGenerator.java
new file mode 100644
index 0000000..dbd27a2
--- /dev/null
+++ b/src/main/java/envoy/data/MessageIdGenerator.java
@@ -0,0 +1,44 @@
+package envoy.data;
+
+/**
+ * Generates increasing IDs between two numbers.
+ *
+ * Project: envoy-common
+ * File: MessageIdGenerator.java
+ * Created: 31.12.2019
+ *
+ * @author Kai S. K. Engelbart
+ * @since Envoy Common v0.2-alpha
+ */
+public class MessageIdGenerator {
+
+ private final long end;
+ private long current;
+
+ /**
+ * Creates an instance of {@link MessageIdGenerator}.
+ *
+ * @param begin the first ID
+ * @param end the last ID
+ * @since Envoy Common v0.2-alpha
+ */
+ public MessageIdGenerator(long begin, long end) {
+ current = begin;
+ this.end = end;
+ }
+
+ /**
+ * @return {@code true} if there are unused IDs remaining
+ * @since Envoy Common v0.2-alpha
+ */
+ public boolean hasNext() { return current < end; }
+
+ /**
+ * @return the next ID
+ * @since Envoy Common v0.2-alpha
+ */
+ public long next() {
+ if (!hasNext()) throw new IllegalStateException("All IDs have been used");
+ return current++;
+ }
+}
diff --git a/src/main/java/envoy/data/TextMessage.java b/src/main/java/envoy/data/TextMessage.java
deleted file mode 100644
index cbee210..0000000
--- a/src/main/java/envoy/data/TextMessage.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package envoy.data;
-
-import java.text.SimpleDateFormat;
-
-/**
- * Represents a {@link Message} with content that is comprised of text.
- *
- * Project: envoy-common
- * File: TextMessage.java
- * Created: 28.12.2019
- *
- * @author Kai S. K. Engelbart
- * @since Envoy Common v0.2-alpha
- */
-public class TextMessage extends Message {
-
- private final String content;
-
- private static final long serialVersionUID = 1538164720632899917L;
-
- /**
- * Initializes a {@link TextMessage} from the client's perspective. The current
- * date
- * is used as the message date and the status is set to
- * {@link envoy.data.Message.MessageStatus#WAITING}.
- *
- * @param id unique ID
- * @param sender the user who sends the message
- * @param recipient the user who receives the message
- * @param content the content of the message
- * @since Envoy Common v0.2-alpha
- */
- public TextMessage(long id, User sender, User recipient, String content) {
- super(id, sender, recipient);
- this.content = content;
- }
-
- @Override
- public String toString() {
- return String.format("TextMessage[id=%d,sender=%s,recipient=%s,date=%s,status=%s,content=%s]",
- getId(),
- getSender(),
- getRecipient(),
- new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(getDate()),
- getStatus(),
- content);
- }
-
- /**
- * @return the content of this {@link TextMessage}
- * @since Envoy Common v0.2-alpha
- */
- public String getContent() { return content; }
-}
\ No newline at end of file
diff --git a/src/main/java/envoy/data/User.java b/src/main/java/envoy/data/User.java
index afca690..d5c0bbc 100644
--- a/src/main/java/envoy/data/User.java
+++ b/src/main/java/envoy/data/User.java
@@ -1,6 +1,8 @@
package envoy.data;
import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
/**
* Represents a unique user with a unique, numeric ID, a name and a current
@@ -9,14 +11,44 @@ import java.io.Serializable;
* Project: envoy-common
* File: User.java
* Created: 28.12.2019
- *
+ *
* @author Kai S. K. Engelbart
* @since Envoy Common v0.2-alpha
*/
public class User implements Serializable {
- private final long id;
- private final String name;
+ /**
+ * This enumeration defines all possible statuses a user can have.
+ *
+ * @since Envoy Common v0.2-alpha
+ */
+ public static enum UserStatus {
+
+ /**
+ * select this, if a user is online and can be interacted with
+ */
+ ONLINE,
+
+ /**
+ * select this, if a user is online but unavailable at the moment (sudden
+ * interruption)
+ */
+ AWAY,
+
+ /**
+ * select this, if a user is online but unavailable at the moment (polite way)
+ */
+ BUSY,
+
+ /**
+ * select this, if a user is offline
+ */
+ OFFLINE;
+ }
+
+ private final long id;
+ private final String name;
+ private final List contacts = new ArrayList<>();
private UserStatus status;
@@ -25,7 +57,7 @@ public class User implements Serializable {
/**
* Initializes a {@link User}. The {@link UserStatus} is set to
* {@link UserStatus#OFFLINE}.
- *
+ *
* @param id unique ID
* @param name user name
* @since Envoy Client v0.2-alpha
@@ -51,6 +83,12 @@ public class User implements Serializable {
*/
public String getName() { return name; }
+ /**
+ * @return a list of all users this user can send messages to
+ * @since Envoy Client v0.2-alpha
+ */
+ public List getContacts() { return contacts; }
+
/**
* @return the current status of this user
* @since Envoy Client v0.2-alpha
@@ -59,13 +97,9 @@ public class User implements Serializable {
/**
* Sets the current status of this user
- *
+ *
* @param status the status to set
* @since Envoy Client v0.2-alpha
*/
public void setStatus(UserStatus status) { this.status = status; }
-
- public static enum UserStatus {
- ONLINE, AWAY, BUSY, OFFLINE;
- }
}
\ No newline at end of file
diff --git a/src/main/java/envoy/event/MessageEvent.java b/src/main/java/envoy/event/MessageEvent.java
index 33a7607..45a7f40 100644
--- a/src/main/java/envoy/event/MessageEvent.java
+++ b/src/main/java/envoy/event/MessageEvent.java
@@ -11,6 +11,9 @@ import envoy.data.Message;
*/
public class MessageEvent implements Event {
+ /**
+ * the {@link Message} attached to this {@link MessageEvent}.
+ */
protected final Message message;
/**
diff --git a/src/main/java/envoy/exception/EnvoyException.java b/src/main/java/envoy/exception/EnvoyException.java
index 00f9946..650e1bb 100644
--- a/src/main/java/envoy/exception/EnvoyException.java
+++ b/src/main/java/envoy/exception/EnvoyException.java
@@ -1,20 +1,35 @@
-package envoy.exception;
-
-/**
- * Project: envoy-common
- * File: EnvoyException.java
- * Created: 27 Oct 2019
- *
- * @author Kai S. K. Engelbart
- * @since Envoy v0.1-alpha
- */
-public class EnvoyException extends Exception {
-
- private static final long serialVersionUID = 2096147309395387479L;
-
- public EnvoyException(String message, Throwable cause) { super(message, cause); }
-
- public EnvoyException(String message) { super(message); }
-
- public EnvoyException(Throwable cause) { super(cause); }
-}
+package envoy.exception;
+
+/**
+ * Project: envoy-common
+ * File: EnvoyException.java
+ * Created: 27 Oct 2019
+ *
+ * @author Kai S. K. Engelbart
+ * @since Envoy v0.1-alpha
+ */
+public class EnvoyException extends Exception {
+
+ private static final long serialVersionUID = 2096147309395387479L;
+
+ /**
+ * @param message the message to display once this Exception is thrown
+ * @since Envoy Common v0.2-alpha
+ */
+ public EnvoyException(String message) { super(message); }
+
+ /**
+ * @param message the message to display once this Exception is thrown
+ * @param cause the {@link Throwable} which resulted in the throw of an
+ * EnvoyException
+ * @since Envoy Common v0.2-alpha
+ */
+ public EnvoyException(String message, Throwable cause) { super(message, cause); }
+
+ /**
+ * @param cause the {@link Throwable} which resulted in the throw of an
+ * EnvoyException
+ * @since Envoy Common v0.2-alpha
+ */
+ public EnvoyException(Throwable cause) { super(cause); }
+}
diff --git a/src/main/java/envoy/util/SerializationUtils.java b/src/main/java/envoy/util/SerializationUtils.java
index dfd166b..c070733 100644
--- a/src/main/java/envoy/util/SerializationUtils.java
+++ b/src/main/java/envoy/util/SerializationUtils.java
@@ -11,28 +11,29 @@ import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
-import envoy.exception.EnvoyException;
-
/**
* Project: envoy-client
* File: SerializationUtils.java
* Created: 23.12.2019
- *
+ *
* @author Kai S. K. Engelbart
* @since Envoy Common v0.2-alpha
*/
public class SerializationUtils {
- private SerializationUtils() {}
+ private static byte[] intToBytes(int n) { return new byte[] { (byte) (n >>> 24), (byte) (n >>> 16), (byte) (n >>> 8), (byte) n }; }
/**
* Deserializes an arbitrary {@link Serializable} object from a file.
- *
+ *
* @param the type of the object to deserialize
- * @param file the file deserialize from
+ * @param file the file to deserialize from
* @param serializedClass the class of the object to deserialize
* @return the deserialized object
- * @throws EnvoyException if an error occurred during deserialization
+ * @throws IOException if something failed while deserializing the
+ * object
+ * @throws ClassNotFoundException if the deserialized object can not be linked
+ * to a class
* @since Envoy Common v0.2-alpha
*/
public static T read(File file, Class serializedClass) throws IOException, ClassNotFoundException {
@@ -40,6 +41,18 @@ public class SerializationUtils {
return read(new FileInputStream(file), serializedClass);
}
+ /**
+ * @param the deserialized object
+ * @param in the {@link InputStream} of a serialized Object
+ * @param serializedClass the object type to convert the deserialized object
+ * into
+ * @return the deserialized object
+ * @throws IOException if something failed while deserializing the
+ * object
+ * @throws ClassNotFoundException if the deserialized object can not be linked
+ * to a class
+ * @since Envoy Common v0.2-alpha
+ */
public static T read(InputStream in, Class serializedClass) throws IOException, ClassNotFoundException {
try (ObjectInputStream oin = new ObjectInputStream(in)) {
return serializedClass.cast(oin.readObject());
@@ -48,7 +61,7 @@ public class SerializationUtils {
/**
* Serializes an arbitrary object to a file.
- *
+ *
* @param file the file to serialize to
* @param obj the object to serialize
* @throws IOException if an error occurred during serialization
@@ -69,7 +82,7 @@ public class SerializationUtils {
/**
* Serializes an object and writes it into an output stream preceded by 4 bytes
* containing the number of serialized bytes.
- *
+ *
* @param obj the object to serialize
* @param out the output stream to serialize to
* @throws IOException if an error occurred during serialization
@@ -90,5 +103,5 @@ public class SerializationUtils {
out.write(objBytes);
}
- private static byte[] intToBytes(int n) { return new byte[] { (byte) (n >>> 24), (byte) (n >>> 16), (byte) (n >>> 8), (byte) n }; }
+ private SerializationUtils() {}
}
\ No newline at end of file