diff --git a/.classpath b/.classpath
index 3603647..e716709 100644
--- a/.classpath
+++ b/.classpath
@@ -1,28 +1,29 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index 0add6eb..98d18f7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,6 +23,7 @@
src/main/resources
+ src/test/java
diff --git a/src/main/java/envoy/data/Contact.java b/src/main/java/envoy/data/Contact.java
index 53992c6..b3b2d03 100644
--- a/src/main/java/envoy/data/Contact.java
+++ b/src/main/java/envoy/data/Contact.java
@@ -2,6 +2,7 @@ package envoy.data;
import java.io.Serializable;
import java.util.Objects;
+import java.util.Set;
/**
* This class is the superclass for both {@link User} and {@link Group}.
@@ -16,21 +17,24 @@ import java.util.Objects;
*/
public abstract class Contact implements Serializable {
- private final long id;
- private String name;
+ private final long id;
+ private final transient Set extends Contact> contacts;
+ private String name;
private static final long serialVersionUID = 0L;
/**
* Creates a new instance of a {@link Contact}.
*
- * @param id the ID of this contact
- * @param name the name of this contact
+ * @param id the ID of this contact
+ * @param name the name of this contact
+ * @param contacts the {@link Contacts} of this {@link Contact}
* @since Envoy Common v0.1-beta
*/
- public Contact(long id, String name) {
- this.id = id;
- this.name = name;
+ public Contact(long id, String name, Set extends Contact> contacts) {
+ this.id = id;
+ this.name = name;
+ this.contacts = contacts;
}
/**
@@ -55,7 +59,7 @@ public abstract class Contact implements Serializable {
* {@inheritDoc}
*/
@Override
- public String toString() { return String.format("Contact[id=%d,name=%s]", id, name); }
+ public String toString() { return String.format("Contact[id=%d,name=%s, contacts=%s]", id, name, contacts); }
/**
* {@inheritDoc}
@@ -72,4 +76,10 @@ public abstract class Contact implements Serializable {
if (!(obj instanceof Contact)) return false;
return id == ((Contact) obj).id;
}
+
+ /**
+ * @return the contacts of this {@link Contact}
+ * @since Envoy Common v0.1-beta
+ */
+ public Set extends Contact> getContacts() { return contacts; }
}
diff --git a/src/main/java/envoy/data/Contacts.java b/src/main/java/envoy/data/Contacts.java
deleted file mode 100644
index 71eac52..0000000
--- a/src/main/java/envoy/data/Contacts.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package envoy.data;
-
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * Project: envoy-common
- * File: Contacts.java
- * Created: 02.01.2020
- *
- * @author Kai S. K. Engelbart
- * @since Envoy Common v0.2-alpha
- */
-public class Contacts implements Serializable {
-
- private final List contacts;
-
- private static final long serialVersionUID = 0L;
-
- /**
- * Creates an instance of {@link Contacts}.
- *
- * @param contacts the contact list
- * @since Envoy Common v0.2-alpha
- */
- public Contacts(List contacts) { this.contacts = contacts; }
-
- @Override
- public String toString() { return String.format("Contacts[%s]", contacts); }
-
- /**
- * @return a list of users messages can be sent to
- * @since Envoy Common v0.2-alpha
- */
- public List getContacts() { return contacts; }
-}
diff --git a/src/main/java/envoy/data/Group.java b/src/main/java/envoy/data/Group.java
index 077ff40..bec17be 100644
--- a/src/main/java/envoy/data/Group.java
+++ b/src/main/java/envoy/data/Group.java
@@ -1,8 +1,9 @@
package envoy.data;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.StringJoiner;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.HashSet;
+import java.util.Set;
/**
* Project: envoy-common
@@ -12,50 +13,44 @@ import java.util.StringJoiner;
* @author Leon Hofmeister
* @since Envoy Common v0.1-beta
*/
-public class Group extends Contact {
-
- // TODO add admins
- private final List memberIDs;
+public final class Group extends Contact {
private static final long serialVersionUID = 0L;
/**
- * Creates a new instance of a {@link Group}.
+ * Creates a new instance of a {@link Group} without any members.
*
* @param id the ID of this group
* @param name the name of this group
* @since Envoy Common v0.1-beta
*/
- public Group(long id, String name) { this(id, name, new ArrayList<>()); }
+ public Group(long id, String name) { this(id, name, new HashSet()); }
/**
- * Creates a new instance of a {@link Group}.
+ * Creates an instance of a {@link Group}.
*
- * @param id the ID of this group
- * @param name the name of this group
- * @param memberIDs the IDs of all members that should be preinitialized
+ * @param id the ID of this group
+ * @param name the name of this group
+ * @param members all members that should be preinitialized
* @since Envoy Common v0.1-beta
*/
- public Group(long id, String name, List memberIDs) {
- super(id, name);
- this.memberIDs = memberIDs;
+ public Group(long id, String name, Set members) { super(id, name, members); }
+
+ private void readObject(ObjectInputStream inputStream) throws Exception {
+ inputStream.defaultReadObject();
+ var contacts = Contact.class.getDeclaredField("contacts");
+ contacts.setAccessible(true);
+ contacts.set(this, inputStream.readObject());
}
- /**
- * @return the IDs of all members of this group
- * @since Envoy Common v0.1-beta
- */
- public List getMemberIDs() { return memberIDs; }
+ private void writeObject(ObjectOutputStream outputStream) throws Exception {
+ outputStream.defaultWriteObject();
+ getContacts().forEach(user -> user.serializeContacts(false));
+ outputStream.writeObject(getContacts());
- /**
- * {@inheritDoc}
- */
+ }
+
+ @SuppressWarnings("unchecked")
@Override
- public String toString() {
- var joiner = new StringJoiner(",", "Group[id=", "]");
- joiner.add("id=" + getID());
- joiner.add("name=" + getName());
- joiner.add("members=" + getMemberIDs().size());
- return joiner.toString();
- }
+ public Set getContacts() { return (Set) super.getContacts(); }
}
diff --git a/src/main/java/envoy/data/MessageBuilder.java b/src/main/java/envoy/data/MessageBuilder.java
index 79325fa..87c6bf9 100644
--- a/src/main/java/envoy/data/MessageBuilder.java
+++ b/src/main/java/envoy/data/MessageBuilder.java
@@ -2,6 +2,7 @@ package envoy.data;
import java.util.Date;
import java.util.HashMap;
+import java.util.Map;
import envoy.data.Message.MessageStatus;
@@ -102,6 +103,35 @@ public class MessageBuilder {
return new Message(id, senderID, recipientID, creationDate, text, attachment, status, forwarded);
}
+ /**
+ * Creates an instance of {@link GroupMessage} with the previously supplied
+ * values.
+ * Sets all member statuses to {@link MessageStatus#WAITING}.
+ * If a mandatory value is not set, a default value will be used
+ * instead:
+ *
+ *
+ *
+ *
{@code date}
+ *
{@code new Date()}
+ *
+ *
+ *
{@code text}
+ *
{@code ""}
+ *
+ *
+ *
+ * @param group the {@link Group} that is used to fill the map of member
+ * statuses
+ * @return a new instance of {@link GroupMessage}
+ * @since Envoy Common v0.2-alpha
+ */
+ public GroupMessage buildGroupMessage(Group group) {
+ var memberStatuses = new HashMap();
+ group.getContacts().forEach(user -> memberStatuses.put(user.getID(), MessageStatus.WAITING));
+ return buildGroupMessage(group, memberStatuses);
+ }
+
/**
* Creates an instance of {@link GroupMessage} with the previously supplied
* values. If a mandatory value is not set, a default value will be used
@@ -116,22 +146,17 @@ public class MessageBuilder {
*
{@code text}
*
{@code ""}
*
- *
- *
{@code status}
- *
{@code MessageStatus.WAITING}
- *
*
*
- * @param group the {@link Group} that is used to fill the map of member
- * statuses
+ * @param group the {@link Group} that is used to fill the map of
+ * member statuses
+ * @param memberStatuses the map of all current statuses
* @return a new instance of {@link GroupMessage}
- * @since Envoy Common v0.2-alpha
+ * @since Envoy Common v0.1-beta
*/
- public GroupMessage buildGroupMessage(Group group) {
- if (group == null) throw new NullPointerException();
+ public GroupMessage buildGroupMessage(Group group, Map memberStatuses) {
+ if (group == null || memberStatuses == null) throw new NullPointerException();
supplyDefaults();
- var memberStatuses = new HashMap();
- group.getMemberIDs().forEach(id -> memberStatuses.put(id, MessageStatus.WAITING));
return new GroupMessage(id, senderID, recipientID, creationDate, text, attachment, status, forwarded, memberStatuses);
}
diff --git a/src/main/java/envoy/data/User.java b/src/main/java/envoy/data/User.java
index d282e29..ca64d0d 100644
--- a/src/main/java/envoy/data/User.java
+++ b/src/main/java/envoy/data/User.java
@@ -1,5 +1,11 @@
package envoy.data;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
/**
* Represents a unique user with a unique, numeric ID, a name and a current
* {@link UserStatus}.
@@ -11,7 +17,16 @@ package envoy.data;
* @author Kai S. K. Engelbart
* @since Envoy Common v0.2-alpha
*/
-public class User extends Contact {
+public final class User extends Contact {
+
+ private UserStatus status;
+
+ /**
+ * Used to serialize contact list to a maximum depth of one
+ */
+ private transient boolean serializeContacts = true;
+
+ private static final long serialVersionUID = 1L;
/**
* This enumeration defines all possible statuses a user can have.
@@ -42,38 +57,50 @@ public class User extends Contact {
OFFLINE;
}
- private UserStatus status;
-
- private static final long serialVersionUID = 1L;
-
/**
* Initializes a {@link User}.
* The {@link UserStatus} is set to {@link UserStatus#ONLINE}.
+ * No contacts are initialized.
*
* @param id unique ID
* @param name user name
* @since Envoy Common v0.2-alpha
*/
public User(long id, String name) {
- super(id, name);
+ super(id, name, new HashSet<>());
+ status = UserStatus.ONLINE;
+ }
+
+ /**
+ * Initializes a {@link User}.
+ * The {@link UserStatus} is set to {@link UserStatus#ONLINE}.
+ *
+ * @param id unique ID
+ * @param name user name
+ * @param contacts the contacts of this user
+ * @since Envoy Common v0.2-alpha
+ */
+ public User(long id, String name, Set contacts) {
+ super(id, name, contacts);
status = UserStatus.ONLINE;
}
/**
* Initializes a {@link User}.
*
- * @param id unique ID
- * @param name user name
- * @param status the status of the user
+ * @param id unique ID
+ * @param name user name
+ * @param status the status of this user
+ * @param contacts the contacts of this user
* @since Envoy Common v0.2-alpha
*/
- public User(long id, String name, UserStatus status) {
- super(id, name);
+ public User(long id, String name, UserStatus status, Set contacts) {
+ super(id, name, contacts);
this.status = status;
}
@Override
- public String toString() { return String.format("User[id=%d,name=%s,status=%s]", getID(), getName(), status); }
+ public String toString() { return String.format("User[id=%d,name=%s,status=%s,contacts=%s]", getID(), getName(), status, getContacts()); }
/**
* @return the current status of this user
@@ -86,4 +113,26 @@ public class User extends Contact {
* @since Envoy Common v0.2-alpha
*/
public void setStatus(UserStatus status) { this.status = status; }
+
+ private void readObject(ObjectInputStream inputStream) throws Exception {
+ inputStream.defaultReadObject();
+ var contacts = Contact.class.getDeclaredField("contacts");
+ contacts.setAccessible(true);
+ contacts.set(this, inputStream.readObject());
+ }
+
+ private void writeObject(ObjectOutputStream outputStream) throws Exception {
+ outputStream.defaultWriteObject();
+ if (serializeContacts) {
+ getContacts().stream().filter(User.class::isInstance).map(User.class::cast).forEach(user -> user.serializeContacts = false);
+ outputStream.writeObject(getContacts());
+ } else outputStream.writeObject(new ArrayList<>());
+ }
+
+ /**
+ * @param serializeContacts whether the contacts of this {@link User} should be
+ * serialized
+ * @since Envoy Common v0.1-beta
+ */
+ public void serializeContacts(boolean serializeContacts) { this.serializeContacts = serializeContacts; }
}
diff --git a/src/main/java/envoy/event/GroupCreationEvent.java b/src/main/java/envoy/event/GroupCreationEvent.java
index 5b6d365..88c405d 100644
--- a/src/main/java/envoy/event/GroupCreationEvent.java
+++ b/src/main/java/envoy/event/GroupCreationEvent.java
@@ -1,5 +1,10 @@
package envoy.event;
+import java.util.HashSet;
+import java.util.Set;
+
+import envoy.data.User;
+
/**
* This event creates a group with the given name.
*
@@ -12,11 +17,26 @@ package envoy.event;
*/
public class GroupCreationEvent extends Event {
+ private final Set initialMemberIDs;
+
private static final long serialVersionUID = 0L;
/**
- * @param value the name of this group at creation time
+ * @param value the name of this group at creation time
+ * @param initialMemberIDs the IDs of all {@link User}s that should be group
+ * members from the beginning on (excluding the creator
+ * of this group)
* @since Envoy Common v0.1-beta
*/
- public GroupCreationEvent(String value) { super(value); }
+ public GroupCreationEvent(String value, Set initialMemberIDs) {
+ super(value);
+ this.initialMemberIDs = (initialMemberIDs != null) ? initialMemberIDs : new HashSet<>();
+ }
+
+ /**
+ * @return the IDs of all {@link User}s that are members from the beginning
+ * (excluding the creator of this group)
+ * @since Envoy Common v0.1-beta
+ */
+ public Set getInitialMemberIDs() { return initialMemberIDs; }
}
diff --git a/src/main/java/envoy/event/GroupResizeEvent.java b/src/main/java/envoy/event/GroupResizeEvent.java
index 24f4ac8..5f6791e 100644
--- a/src/main/java/envoy/event/GroupResizeEvent.java
+++ b/src/main/java/envoy/event/GroupResizeEvent.java
@@ -36,7 +36,7 @@ public class GroupResizeEvent extends Event {
*/
public GroupResizeEvent(User user, Group group, ElementOperation operation) {
super(user.getID());
- if (group.getMemberIDs().contains(user.getID())) {
+ if (group.getContacts().contains(user)) {
if (operation.equals(ElementOperation.ADD)) throw new IllegalStateException(
"Cannot add " + user + " to group " + group.getID() + " because he is already a member of this group");
} else if (operation.equals(ElementOperation.REMOVE))
diff --git a/src/test/java/envoy/data/UserTest.java b/src/test/java/envoy/data/UserTest.java
new file mode 100644
index 0000000..b04134d
--- /dev/null
+++ b/src/test/java/envoy/data/UserTest.java
@@ -0,0 +1,35 @@
+package envoy.data;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.junit.jupiter.api.Test;
+
+import envoy.data.User.UserStatus;
+import envoy.util.SerializationUtils;
+
+/**
+ * Project: envoy-common
+ * File: UserTest.java
+ * Created: 31 Mar 2020
+ *
+ * @author Leon Hofmeister
+ * @since Envoy Common v0.1-beta
+ */
+class UserTest {
+
+ @Test
+ void test() throws IOException, ClassNotFoundException {
+ User user2 = new User(2, "kai");
+ User user3 = new User(3, "ai");
+ User user4 = new User(4, "ki", Set.of(user2, user3));
+ User user5 = new User(5, "ka", Set.of(user2, user3, user4));
+ User user = new User(1, "maxi", UserStatus.AWAY, Set.of(user2, user3, user4, user5));
+ var serializedUser = SerializationUtils.writeToByteArray(user);
+ var deserializedUser = SerializationUtils.read(serializedUser, User.class);
+ assertEquals(user.getContacts(), deserializedUser.getContacts());
+ }
+
+}