deleted Contacts object, added contacts as part of Contact class
additionally: * updated serialization method to not recurse endlessly * refactored type of contacts from List to Set
This commit is contained in:
parent
c41089e005
commit
0d3316be4a
57
.classpath
57
.classpath
@ -1,28 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
1
pom.xml
1
pom.xml
@ -23,6 +23,7 @@
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<testSourceDirectory>src/test/java</testSourceDirectory>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
@ -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}.<br>
|
||||
@ -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; }
|
||||
}
|
||||
|
@ -1,36 +0,0 @@
|
||||
package envoy.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Project: <strong>envoy-common</strong><br>
|
||||
* File: <strong>Contacts.java</strong><br>
|
||||
* Created: <strong>02.01.2020</strong><br>
|
||||
*
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Common v0.2-alpha
|
||||
*/
|
||||
public class Contacts implements Serializable {
|
||||
|
||||
private final List<Contact> 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<Contact> 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<Contact> getContacts() { return contacts; }
|
||||
}
|
@ -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: <strong>envoy-common</strong><br>
|
||||
@ -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<Long> 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<User>()); }
|
||||
|
||||
/**
|
||||
* 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<Long> memberIDs) {
|
||||
super(id, name);
|
||||
this.memberIDs = memberIDs;
|
||||
public Group(long id, String name, Set<User> 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<Long> 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<User> getContacts() { return (Set<User>) super.getContacts(); }
|
||||
}
|
||||
|
@ -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. <br>
|
||||
* <b> Sets all member statuses to {@link MessageStatus#WAITING}.</b><br>
|
||||
* If a mandatory value is not set, a default value will be used
|
||||
* instead:<br>
|
||||
* <br>
|
||||
* <table border="1">
|
||||
* <tr>
|
||||
* <td>{@code date}</td>
|
||||
* <td>{@code new Date()}</td>
|
||||
* <tr>
|
||||
* <tr>
|
||||
* <td>{@code text}</td>
|
||||
* <td>{@code ""}</td>
|
||||
* <tr>
|
||||
* </table>
|
||||
*
|
||||
* @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<Long, Message.MessageStatus>();
|
||||
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 {
|
||||
* <td>{@code text}</td>
|
||||
* <td>{@code ""}</td>
|
||||
* <tr>
|
||||
* <tr>
|
||||
* <td>{@code status}</td>
|
||||
* <td>{@code MessageStatus.WAITING}</td>
|
||||
* <tr>
|
||||
* </table>
|
||||
*
|
||||
* @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<Long, MessageStatus> memberStatuses) {
|
||||
if (group == null || memberStatuses == null) throw new NullPointerException();
|
||||
supplyDefaults();
|
||||
var memberStatuses = new HashMap<Long, Message.MessageStatus>();
|
||||
group.getMemberIDs().forEach(id -> memberStatuses.put(id, MessageStatus.WAITING));
|
||||
return new GroupMessage(id, senderID, recipientID, creationDate, text, attachment, status, forwarded, memberStatuses);
|
||||
}
|
||||
|
||||
|
@ -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}.<br>
|
||||
@ -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}. <br>
|
||||
* 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}. <br>
|
||||
* 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<Contact> 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<Contact> 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; }
|
||||
}
|
||||
|
@ -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.<br>
|
||||
* <br>
|
||||
@ -12,11 +17,26 @@ package envoy.event;
|
||||
*/
|
||||
public class GroupCreationEvent extends Event<String> {
|
||||
|
||||
private final Set<Long> 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<Long> 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<Long> getInitialMemberIDs() { return initialMemberIDs; }
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public class GroupResizeEvent extends Event<Long> {
|
||||
*/
|
||||
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))
|
||||
|
35
src/test/java/envoy/data/UserTest.java
Normal file
35
src/test/java/envoy/data/UserTest.java
Normal file
@ -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: <strong>envoy-common</strong><br>
|
||||
* File: <strong>UserTest.java</strong><br>
|
||||
* Created: <strong>31 Mar 2020</strong><br>
|
||||
*
|
||||
* @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());
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user