diff --git a/src/io/github/norbipeti/chat/server/data/DataManager.java b/src/io/github/norbipeti/chat/server/data/DataManager.java index 44d2db6..83e5448 100644 --- a/src/io/github/norbipeti/chat/server/data/DataManager.java +++ b/src/io/github/norbipeti/chat/server/data/DataManager.java @@ -10,13 +10,13 @@ import java.util.Map; import com.google.common.io.Files; import io.github.norbipeti.chat.server.Main; -import io.github.norbipeti.chat.server.db.domain.ChatDatabaseEntity; +import io.github.norbipeti.chat.server.db.domain.SavedData; public final class DataManager { private DataManager() { } - public static void save(T object) { + public static void save(T object) { try { Files.write(Main.gson.toJson(object), new File(object.getClass().getName() + "-" + object.getId()), StandardCharsets.UTF_8); @@ -25,11 +25,11 @@ public final class DataManager { } } - public static T load(Class cl, long id) { + public static T load(Class cl, long id) { return loadFromFile(new File(cl.getName() + "-" + id), cl); } - public static LoaderCollection load(Class cl) { + public static LoaderCollection load(Class cl) { String[] filenames = new File(".").list(new FilenameFilter() { @Override @@ -46,9 +46,10 @@ public final class DataManager { private static Map cache = new HashMap<>(); // TODO: Remove objects from the cache over time + // TODO: Save the object when it happens @SuppressWarnings("unchecked") - private static T loadFromFile(File file, Class cl) { + private static T loadFromFile(File file, Class cl) { try { if (!file.exists()) return cl.newInstance(); @@ -68,13 +69,13 @@ public final class DataManager { return null; } - public static boolean remove(T obj) { + public static boolean remove(T obj) { if (cache.containsValue(obj)) cache.values().remove(obj); return new File(obj.getClass().getName() + "-" + obj.getId()).delete(); } - public static boolean remove(Class cl, Long id) { + public static boolean remove(Class cl, Long id) { return new File(cl.getName() + "-" + id).delete(); } } diff --git a/src/io/github/norbipeti/chat/server/data/LoaderCollection.java b/src/io/github/norbipeti/chat/server/data/LoaderCollection.java index e3cda8c..a50b457 100644 --- a/src/io/github/norbipeti/chat/server/data/LoaderCollection.java +++ b/src/io/github/norbipeti/chat/server/data/LoaderCollection.java @@ -8,9 +8,21 @@ import java.util.List; import java.util.ListIterator; import java.util.stream.Collectors; -import io.github.norbipeti.chat.server.db.domain.ChatDatabaseEntity; +import io.github.norbipeti.chat.server.db.domain.SavedData; -public class LoaderCollection implements List, Serializable { +/** + *

+ * This list wil only load it's items when directly accessed + *

+ *

+ * And it will only save IDs of it's items + *

+ * + * @author Norbi + * + * @param + */ +public class LoaderCollection implements List, Serializable { private static final long serialVersionUID = 5426152406394894301L; List idlist; Class cl; @@ -57,7 +69,7 @@ public class LoaderCollection implements List, @Override public boolean addAll(Collection c) { return idlist.addAll(c.stream().map((data) -> { - ChatDatabaseEntity cde = ((ChatDatabaseEntity) data); + SavedData cde = ((SavedData) data); DataManager.save(cde); return cde.getId(); }).collect(Collectors.toList())); @@ -66,7 +78,7 @@ public class LoaderCollection implements List, @Override public boolean addAll(int index, Collection c) { return idlist.addAll(index, c.stream().map((data) -> { - ChatDatabaseEntity cde = ((ChatDatabaseEntity) data); + SavedData cde = ((SavedData) data); DataManager.save(cde); return cde.getId(); }).collect(Collectors.toList())); @@ -75,7 +87,7 @@ public class LoaderCollection implements List, @Override public void clear() { for (Long id : idlist) - DataManager.remove(cl, id); //TODO: Move out to a main list + DataManager.remove(cl, id); // TODO: Move out to a main list idlist.clear(); } @@ -127,9 +139,9 @@ public class LoaderCollection implements List, */ @Override public boolean remove(Object o) { - if (ChatDatabaseEntity.class.isAssignableFrom(o.getClass())) { - DataManager.remove((ChatDatabaseEntity) o); - return idlist.remove(((ChatDatabaseEntity) o).getId()); + if (SavedData.class.isAssignableFrom(o.getClass())) { + DataManager.remove((SavedData) o); + return idlist.remove(((SavedData) o).getId()); } if (Long.class.isAssignableFrom(o.getClass())) DataManager.remove(cl, (Long) o); @@ -145,8 +157,8 @@ public class LoaderCollection implements List, public boolean removeAll(Collection c) { boolean success = false; for (Object item : c) { - if (ChatDatabaseEntity.class.isAssignableFrom(item.getClass())) { - if (idlist.remove(((ChatDatabaseEntity) item).getId())) { + if (SavedData.class.isAssignableFrom(item.getClass())) { + if (idlist.remove(((SavedData) item).getId())) { success = true; break; } @@ -164,8 +176,8 @@ public class LoaderCollection implements List, public boolean retainAll(Collection c) { List list = new ArrayList(); for (Object item : c) { - if (ChatDatabaseEntity.class.isAssignableFrom(item.getClass())) { - list.add(((ChatDatabaseEntity) item).getId()); + if (SavedData.class.isAssignableFrom(item.getClass())) { + list.add(((SavedData) item).getId()); } else if (Long.class.isAssignableFrom(item.getClass())) { list.add((Long) item); } diff --git a/src/io/github/norbipeti/chat/server/data/LoaderCollectionSerializer.java b/src/io/github/norbipeti/chat/server/data/LoaderCollectionSerializer.java index c1fab91..0a856be 100644 --- a/src/io/github/norbipeti/chat/server/data/LoaderCollectionSerializer.java +++ b/src/io/github/norbipeti/chat/server/data/LoaderCollectionSerializer.java @@ -9,13 +9,13 @@ import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; -import io.github.norbipeti.chat.server.db.domain.ChatDatabaseEntity; +import io.github.norbipeti.chat.server.db.domain.SavedData; //@SuppressWarnings("rawtypes") -public class LoaderCollectionSerializer extends TypeAdapter> { +public class LoaderCollectionSerializer extends TypeAdapter> { @Override - public void write(JsonWriter out, LoaderCollection value) throws IOException { + public void write(JsonWriter out, LoaderCollection value) throws IOException { out.beginObject(); out.name("items"); new Gson().toJson(value.idlist, new TypeToken>() { @@ -27,7 +27,7 @@ public class LoaderCollectionSerializer extends Ty // @SuppressWarnings("unchecked") @SuppressWarnings("unchecked") @Override - public LoaderCollection read(JsonReader in) throws IOException { + public LoaderCollection read(JsonReader in) throws IOException { in.beginObject(); in.nextName(); List list = new Gson().fromJson(in, new TypeToken>() { @@ -36,14 +36,15 @@ public class LoaderCollectionSerializer extends Ty new Exception("Error: Next isn't \"class\"").printStackTrace(); return null; } - Class cl; + Class cl; try { - cl = (Class) Class.forName(in.nextString()); + cl = (Class) Class.forName(in.nextString()); } catch (ClassNotFoundException e) { e.printStackTrace(); return null; } - LoaderCollection col = new LoaderCollection(cl); // TODO + LoaderCollection col = new LoaderCollection( + (Class) cl); // TODO col.idlist.addAll(list); in.endObject(); return col; diff --git a/src/io/github/norbipeti/chat/server/data/LoaderIterator.java b/src/io/github/norbipeti/chat/server/data/LoaderIterator.java index 99ad816..ed2b3cb 100644 --- a/src/io/github/norbipeti/chat/server/data/LoaderIterator.java +++ b/src/io/github/norbipeti/chat/server/data/LoaderIterator.java @@ -1,9 +1,9 @@ package io.github.norbipeti.chat.server.data; import java.util.Iterator; -import io.github.norbipeti.chat.server.db.domain.ChatDatabaseEntity; +import io.github.norbipeti.chat.server.db.domain.SavedData; -public final class LoaderIterator implements Iterator { +public final class LoaderIterator implements Iterator { private Iterator iterator; private T lastitem; private Class cl; diff --git a/src/io/github/norbipeti/chat/server/data/LoaderListIterator.java b/src/io/github/norbipeti/chat/server/data/LoaderListIterator.java index 2d87537..f391c1d 100644 --- a/src/io/github/norbipeti/chat/server/data/LoaderListIterator.java +++ b/src/io/github/norbipeti/chat/server/data/LoaderListIterator.java @@ -2,9 +2,9 @@ package io.github.norbipeti.chat.server.data; import java.util.ListIterator; -import io.github.norbipeti.chat.server.db.domain.ChatDatabaseEntity; +import io.github.norbipeti.chat.server.db.domain.SavedData; -public final class LoaderListIterator implements ListIterator { +public final class LoaderListIterator implements ListIterator { private ListIterator listiterator; private T lastitem; private Class cl; diff --git a/src/io/github/norbipeti/chat/server/data/LoaderRef.java b/src/io/github/norbipeti/chat/server/data/LoaderRef.java new file mode 100644 index 0000000..f0cb12b --- /dev/null +++ b/src/io/github/norbipeti/chat/server/data/LoaderRef.java @@ -0,0 +1,37 @@ +package io.github.norbipeti.chat.server.data; + +import io.github.norbipeti.chat.server.db.domain.SavedData; + +/** + *

+ * This class will only store IDs and load the object when calling + * {@link #get()} + *

+ *

+ * And will also only save IDs when serialized with {@link LoaderRefSerializer} + *

+ * + * @author Norbi + * + * @param + * The type of the stored object + */ +public class LoaderRef { + Class cl; + Long id; + + public LoaderRef(Class cl, Long id) { + this.id = id; + this.cl = cl; + } + + @SuppressWarnings("unchecked") + public LoaderRef(T obj) { + this.id = obj.getId(); + this.cl = (Class) obj.getClass(); + } + + public T get() { + return DataManager.load(cl, id); + } +} diff --git a/src/io/github/norbipeti/chat/server/data/LoaderRefSerializer.java b/src/io/github/norbipeti/chat/server/data/LoaderRefSerializer.java new file mode 100644 index 0000000..bc423ec --- /dev/null +++ b/src/io/github/norbipeti/chat/server/data/LoaderRefSerializer.java @@ -0,0 +1,52 @@ +package io.github.norbipeti.chat.server.data; + +import java.io.IOException; +import java.util.List; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +import io.github.norbipeti.chat.server.db.domain.SavedData; + +//@SuppressWarnings("rawtypes") +public class LoaderRefSerializer extends TypeAdapter> { + + @Override + public void write(JsonWriter out, LoaderRef value) throws IOException { + out.beginObject(); + out.name("items"); + new Gson().toJson(value.id, new TypeToken>() { + }.getType(), out); + out.name("class").value(value.cl.getName()); + out.endObject(); + } + + // @SuppressWarnings("unchecked") + @SuppressWarnings("unchecked") + @Override + public LoaderRef read(JsonReader in) throws IOException { + in.beginObject(); + in.nextName(); + Long id = new Gson().fromJson(in, new TypeToken() { + }.getType()); + if (!in.nextName().equals("class")) { + new Exception("Error: Next isn't \"class\"").printStackTrace(); + return null; + } + Class cl; + try { + cl = (Class) Class.forName(in.nextString()); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + return null; + } + LoaderRef col = new LoaderRef( + (Class) cl, id); // TODO + in.endObject(); + return col; + } + +} diff --git a/src/io/github/norbipeti/chat/server/db/DataProvider.java b/src/io/github/norbipeti/chat/server/db/DataProvider.java index 74d7099..48448bf 100644 --- a/src/io/github/norbipeti/chat/server/db/DataProvider.java +++ b/src/io/github/norbipeti/chat/server/db/DataProvider.java @@ -20,7 +20,7 @@ public class DataProvider implements AutoCloseable { em.getTransaction().begin(); } - public T save(T object) { + public T save(T object) { T obj = em.merge(object); return obj; } diff --git a/src/io/github/norbipeti/chat/server/db/domain/Conversation.java b/src/io/github/norbipeti/chat/server/db/domain/Conversation.java index d3ce22b..a01d60a 100644 --- a/src/io/github/norbipeti/chat/server/db/domain/Conversation.java +++ b/src/io/github/norbipeti/chat/server/db/domain/Conversation.java @@ -6,7 +6,7 @@ import io.github.norbipeti.chat.server.data.LoaderCollection; @Entity @Table(name = "CONVERSATION") -public class Conversation extends ChatDatabaseEntity { +public class Conversation extends SavedData { private static final long serialVersionUID = 5058682475353799722L; // @Id // @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -14,7 +14,7 @@ public class Conversation extends ChatDatabaseEntity { // private Long id; @ElementCollection(fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "conversation") - private LoaderCollection messsages = new LoaderCollection<>(Message.class); + private LoaderCollection messsagechunks = new LoaderCollection<>(MessageChunk.class); @ElementCollection(fetch = FetchType.EAGER) @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) // @JoinTable(name = "User_Conversation", joinColumns = @JoinColumn(name = @@ -28,12 +28,12 @@ public class Conversation extends ChatDatabaseEntity { // @JoinTable(name = "User_Conversation") private LoaderCollection users = new LoaderCollection<>(User.class); - public LoaderCollection getMesssages() { - return messsages; + public LoaderCollection getMesssageChunks() { + return messsagechunks; } - public void setMesssages(LoaderCollection messsages) { - this.messsages = messsages; + public void setMesssageChunks(LoaderCollection messsages) { + this.messsagechunks = messsages; } public LoaderCollection getUsers() { diff --git a/src/io/github/norbipeti/chat/server/db/domain/Message.java b/src/io/github/norbipeti/chat/server/db/domain/Message.java index 3b0762b..fb181ce 100644 --- a/src/io/github/norbipeti/chat/server/db/domain/Message.java +++ b/src/io/github/norbipeti/chat/server/db/domain/Message.java @@ -1,17 +1,20 @@ package io.github.norbipeti.chat.server.db.domain; +import java.io.Serializable; import java.util.Date; import javax.persistence.*; +import io.github.norbipeti.chat.server.data.LoaderRef; + @Entity @Table(name = "MESSAGE") -public class Message extends ChatDatabaseEntity { +public class Message implements Serializable { private static final long serialVersionUID = 6345941601716826570L; - //@Id - //@GeneratedValue(strategy = GenerationType.IDENTITY) - //@Column(name = "ID", unique = true, nullable = false) - //private Long id; + // @Id + // @GeneratedValue(strategy = GenerationType.IDENTITY) + // @Column(name = "ID", unique = true, nullable = false) + // private Long id; @ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER) // @JoinTable(name="user_message") private User sender; @@ -19,7 +22,7 @@ public class Message extends ChatDatabaseEntity { private String message; @ManyToOne(fetch = FetchType.EAGER) // @JoinTable(name="conversation_message") - private Conversation conversation; + private LoaderRef messagechunk; public User getSender() { return sender; @@ -45,19 +48,17 @@ public class Message extends ChatDatabaseEntity { this.message = message; } - public Conversation getConversation() { - return conversation; + public LoaderRef getMessageChunk() { + return messagechunk; } - public void setConversation(Conversation conversation) { - this.conversation = conversation; + public void setMessageChunk(LoaderRef messagechunk) { + this.messagechunk = messagechunk; } - /*public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - }*/ + /* + * public Long getId() { return id; } + * + * public void setId(Long id) { this.id = id; } + */ } diff --git a/src/io/github/norbipeti/chat/server/db/domain/MessageChunk.java b/src/io/github/norbipeti/chat/server/db/domain/MessageChunk.java new file mode 100644 index 0000000..266050d --- /dev/null +++ b/src/io/github/norbipeti/chat/server/db/domain/MessageChunk.java @@ -0,0 +1,29 @@ +package io.github.norbipeti.chat.server.db.domain; + +import java.util.ArrayList; +import java.util.List; + +import io.github.norbipeti.chat.server.data.LoaderRef; + +public class MessageChunk extends SavedData { + private static final long serialVersionUID = -1665300779209348467L; + + private List messages = new ArrayList<>(); + private LoaderRef conversation; + + public List getMessages() { + return messages; + } + + public void setMessages(List messages) { + this.messages = messages; + } + + public LoaderRef getConversation() { + return conversation; + } + + public void setConversation(LoaderRef conversation) { + this.conversation = conversation; + } +} diff --git a/src/io/github/norbipeti/chat/server/db/domain/SavedData.java b/src/io/github/norbipeti/chat/server/db/domain/SavedData.java index 2125011..b90ecc5 100644 --- a/src/io/github/norbipeti/chat/server/db/domain/SavedData.java +++ b/src/io/github/norbipeti/chat/server/db/domain/SavedData.java @@ -3,7 +3,7 @@ package io.github.norbipeti.chat.server.db.domain; import java.io.Serializable; @SuppressWarnings("serial") -public abstract class ChatDatabaseEntity implements Serializable { +public abstract class SavedData implements Serializable { private static long nextID = 0; private long id; @@ -12,7 +12,7 @@ public abstract class ChatDatabaseEntity implements Serializable { return id; } - protected ChatDatabaseEntity() { + protected SavedData() { id = nextID++; } } diff --git a/src/io/github/norbipeti/chat/server/db/domain/User.java b/src/io/github/norbipeti/chat/server/db/domain/User.java index 55a3be1..5221b71 100644 --- a/src/io/github/norbipeti/chat/server/db/domain/User.java +++ b/src/io/github/norbipeti/chat/server/db/domain/User.java @@ -9,7 +9,7 @@ import io.github.norbipeti.chat.server.data.LoaderCollection; @Entity @Table(name = "\"USER\"") -public class User extends ChatDatabaseEntity { +public class User extends SavedData { private static final long serialVersionUID = 2862762084164225666L; // @Id // @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/io/github/norbipeti/chat/server/page/IndexPage.java b/src/io/github/norbipeti/chat/server/page/IndexPage.java index be7962a..d446783 100644 --- a/src/io/github/norbipeti/chat/server/page/IndexPage.java +++ b/src/io/github/norbipeti/chat/server/page/IndexPage.java @@ -45,8 +45,8 @@ public class IndexPage extends Page { cide.attr("style", "display: none"); cide.attr("id", "convidp"); cide.text(Long.toString(conv.getId())); - LogManager.getLogger().log(Level.INFO, "Messages: " + conv.getMesssages().size()); - for (Message message : conv.getMesssages()) { + LogManager.getLogger().log(Level.INFO, "Messages: " + conv.getMesssageChunks().size()); + for (Message message : conv.getMesssageChunks()) { Element msgelement = channelmessages.appendElement("div"); //TODO: Save messages in conversation files Element header = msgelement.appendElement("p"); header.text(message.getSender().getName() + " - " + message.getTime()); diff --git a/src/io/github/norbipeti/chat/server/page/MessageAjaxPage.java b/src/io/github/norbipeti/chat/server/page/MessageAjaxPage.java index 368cba5..f6b501e 100644 --- a/src/io/github/norbipeti/chat/server/page/MessageAjaxPage.java +++ b/src/io/github/norbipeti/chat/server/page/MessageAjaxPage.java @@ -72,9 +72,9 @@ public class MessageAjaxPage extends Page { msg.setTime(new Date()); msg.setConversation(conv); // TODO: Store relations at one side or both DataManager.save(msg); - conv.getMesssages().add(msg); + conv.getMesssageChunks().add(msg); DataManager.save(conv); - LogManager.getLogger().log(Level.DEBUG, "Added conversation's message count: " + conv.getMesssages().size()); + LogManager.getLogger().log(Level.DEBUG, "Added conversation's message count: " + conv.getMesssageChunks().size()); IOHelper.SendResponse(200, "Success", exchange); }