Fixed LoaderCollection serialization
This commit is contained in:
parent
8068b292cf
commit
3a1f2a65e1
8 changed files with 125 additions and 95 deletions
|
@ -4,6 +4,7 @@ import java.lang.reflect.Modifier;
|
|||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
@ -12,18 +13,34 @@ import org.reflections.Reflections;
|
|||
import org.reflections.scanners.SubTypesScanner;
|
||||
import org.reflections.util.ClasspathHelper;
|
||||
import org.reflections.util.ConfigurationBuilder;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
|
||||
import io.github.norbipeti.chat.server.data.DataManager;
|
||||
import io.github.norbipeti.chat.server.data.LoaderCollection;
|
||||
import io.github.norbipeti.chat.server.data.LoaderCollectionSerializer;
|
||||
import io.github.norbipeti.chat.server.db.domain.*;
|
||||
import io.github.norbipeti.chat.server.page.*;
|
||||
|
||||
public class Main {
|
||||
public static Gson gson;
|
||||
|
||||
public static void main(String[] args) { // http://stackoverflow.com/questions/9266632/access-restriction-is-not-accessible-due-to-restriction-on-required-library/10642163#10642163
|
||||
try { // rt.jar Javadoc:
|
||||
// https://docs.oracle.com/javase/8/docs/jre/api/net/httpserver/spec/
|
||||
// https://docs.oracle.com/javase/8/docs/api/
|
||||
LogManager.getLogger().log(Level.INFO, "Loading database...");
|
||||
LogManager.getLogger().log(Level.INFO, "Loading files...");
|
||||
final GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
gsonBuilder.registerTypeAdapter(new TypeToken<LoaderCollection<Conversation>>() {
|
||||
}.getType(), new LoaderCollectionSerializer<Conversation>());
|
||||
gsonBuilder.registerTypeAdapter(new TypeToken<LoaderCollection<Message>>() {
|
||||
}.getType(), new LoaderCollectionSerializer<Message>());
|
||||
gsonBuilder.registerTypeAdapter(new TypeToken<LoaderCollection<User>>() {
|
||||
}.getType(), new LoaderCollectionSerializer<User>());
|
||||
gson = gsonBuilder.create();
|
||||
User user = new User();
|
||||
user.setName("asd");
|
||||
user.setEmail("test@test.com");
|
||||
|
|
|
@ -6,7 +6,7 @@ import java.io.FilenameFilter;
|
|||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.gson.Gson;
|
||||
import io.github.norbipeti.chat.server.Main;
|
||||
import io.github.norbipeti.chat.server.db.domain.ChatDatabaseEntity;
|
||||
|
||||
public final class DataManager {
|
||||
|
@ -14,8 +14,7 @@ public final class DataManager {
|
|||
}
|
||||
|
||||
public static <T extends ChatDatabaseEntity> void save(T object) throws IOException {
|
||||
Gson gson = new Gson();
|
||||
Files.write(gson.toJson(object), new File(object.getClass().getName() + "-" + object.getId()),
|
||||
Files.write(Main.gson.toJson(object), new File(object.getClass().getName() + "-" + object.getId()),
|
||||
StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
|
@ -47,8 +46,7 @@ public final class DataManager {
|
|||
String line;
|
||||
while ((line = reader.readLine()) != null)
|
||||
objstr += line;
|
||||
Gson gson = new Gson();
|
||||
return gson.fromJson(objstr, cl);
|
||||
return Main.gson.fromJson(objstr, cl);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -12,9 +12,8 @@ import io.github.norbipeti.chat.server.db.domain.ChatDatabaseEntity;
|
|||
|
||||
public class LoaderCollection<T extends ChatDatabaseEntity> implements List<T>, Serializable {
|
||||
private static final long serialVersionUID = 5426152406394894301L;
|
||||
private List<Long> contacts;
|
||||
private Class<T> cl;
|
||||
private transient boolean forsave = false;
|
||||
List<Long> idlist;
|
||||
Class<T> cl;
|
||||
|
||||
/**
|
||||
* Only used for serialization
|
||||
|
@ -25,92 +24,89 @@ public class LoaderCollection<T extends ChatDatabaseEntity> implements List<T>,
|
|||
|
||||
public LoaderCollection(Class<T> cl) {
|
||||
this.cl = cl;
|
||||
contacts = new ArrayList<>();
|
||||
idlist = new ArrayList<>();
|
||||
}
|
||||
|
||||
public LoaderCollection(LoaderCollection<T> parentofsub, int fromIndex, int toIndex) {
|
||||
this.cl = parentofsub.cl;
|
||||
contacts = parentofsub.contacts.subList(fromIndex, toIndex);
|
||||
idlist = parentofsub.idlist.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
public LoaderCollection(Class<T> cl, int capacity) {
|
||||
this.cl = cl;
|
||||
contacts = new ArrayList<>(capacity);
|
||||
idlist = new ArrayList<>(capacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
if (forsave)
|
||||
return contacts.iterator(); // TODO: Fix
|
||||
else
|
||||
return new LoaderIterator<T>(contacts.iterator(), cl);
|
||||
return new LoaderIterator<T>(idlist.iterator(), cl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T e) {
|
||||
return contacts.add(e.getId());
|
||||
return idlist.add(e.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, T element) {
|
||||
contacts.add(index, element.getId());
|
||||
idlist.add(index, element.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> c) {
|
||||
return contacts
|
||||
return idlist
|
||||
.addAll(c.stream().map((data) -> ((ChatDatabaseEntity) data).getId()).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends T> c) {
|
||||
return contacts.addAll(index,
|
||||
return idlist.addAll(index,
|
||||
c.stream().map((data) -> ((ChatDatabaseEntity) data).getId()).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
contacts.clear();
|
||||
idlist.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return contacts.contains(o);
|
||||
return idlist.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return contacts.containsAll(c);
|
||||
return idlist.containsAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(int index) {
|
||||
return DataManager.load(cl, contacts.get(index));
|
||||
return DataManager.load(cl, idlist.get(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
return contacts.indexOf(o);
|
||||
return idlist.indexOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return contacts.isEmpty();
|
||||
return idlist.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
return contacts.lastIndexOf(o);
|
||||
return idlist.lastIndexOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<T> listIterator() {
|
||||
return new LoaderListIterator<T>(contacts.listIterator(), cl);
|
||||
return new LoaderListIterator<T>(idlist.listIterator(), cl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<T> listIterator(int index) {
|
||||
return new LoaderListIterator<T>(contacts.listIterator(index), cl);
|
||||
return new LoaderListIterator<T>(idlist.listIterator(index), cl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,13 +118,13 @@ public class LoaderCollection<T extends ChatDatabaseEntity> implements List<T>,
|
|||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if (ChatDatabaseEntity.class.isAssignableFrom(o.getClass()))
|
||||
return contacts.remove(((ChatDatabaseEntity) o).getId());
|
||||
return contacts.remove(o);
|
||||
return idlist.remove(((ChatDatabaseEntity) o).getId());
|
||||
return idlist.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T remove(int index) {
|
||||
return DataManager.load(cl, contacts.remove(index));
|
||||
return DataManager.load(cl, idlist.remove(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -136,12 +132,12 @@ public class LoaderCollection<T extends ChatDatabaseEntity> implements List<T>,
|
|||
boolean success = false;
|
||||
for (Object item : c) {
|
||||
if (ChatDatabaseEntity.class.isAssignableFrom(item.getClass())) {
|
||||
if (contacts.remove(((ChatDatabaseEntity) item).getId())) {
|
||||
if (idlist.remove(((ChatDatabaseEntity) item).getId())) {
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (contacts.remove(item)) {
|
||||
if (idlist.remove(item)) {
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
@ -160,17 +156,17 @@ public class LoaderCollection<T extends ChatDatabaseEntity> implements List<T>,
|
|||
list.add((Long) item);
|
||||
}
|
||||
}
|
||||
return contacts.retainAll(list);
|
||||
return idlist.retainAll(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T set(int index, T element) {
|
||||
return DataManager.load(cl, contacts.set(index, element.getId()));
|
||||
return DataManager.load(cl, idlist.set(index, element.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return contacts.size();
|
||||
return idlist.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -181,14 +177,14 @@ public class LoaderCollection<T extends ChatDatabaseEntity> implements List<T>,
|
|||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return contacts.stream().map((data) -> {
|
||||
return idlist.stream().map((data) -> {
|
||||
return DataManager.load(cl, data);
|
||||
}).collect(Collectors.toList()).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U> U[] toArray(U[] a) {
|
||||
return contacts.stream().map((data) -> {
|
||||
return idlist.stream().map((data) -> {
|
||||
return DataManager.load(cl, data);
|
||||
}).collect(Collectors.toList()).toArray(a);
|
||||
}
|
||||
|
@ -200,7 +196,7 @@ public class LoaderCollection<T extends ChatDatabaseEntity> implements List<T>,
|
|||
|
||||
public String toString(boolean loaditems) {
|
||||
StringBuilder sb = new StringBuilder("[");
|
||||
for (Long item : contacts) {
|
||||
for (Long item : idlist) {
|
||||
if (loaditems)
|
||||
sb.append(DataManager.load(cl, item));
|
||||
else
|
||||
|
@ -209,12 +205,4 @@ public class LoaderCollection<T extends ChatDatabaseEntity> implements List<T>,
|
|||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean isForsave() {
|
||||
return forsave;
|
||||
}
|
||||
|
||||
public void setForsave(boolean forsave) {
|
||||
this.forsave = forsave;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.ChatDatabaseEntity;
|
||||
|
||||
//@SuppressWarnings("rawtypes")
|
||||
public class LoaderCollectionSerializer<T extends ChatDatabaseEntity> extends TypeAdapter<LoaderCollection<T>> {
|
||||
|
||||
@Override
|
||||
public void write(JsonWriter out, LoaderCollection<T> value) throws IOException {
|
||||
out.beginObject();
|
||||
out.name("items");
|
||||
new Gson().toJson(value.idlist, new TypeToken<List<Long>>() {
|
||||
}.getType(), out);
|
||||
out.name("class").value(value.cl.getName());
|
||||
out.endObject();
|
||||
}
|
||||
|
||||
// @SuppressWarnings("unchecked")
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public LoaderCollection<T> read(JsonReader in) throws IOException {
|
||||
in.beginObject();
|
||||
in.nextName();
|
||||
List<Long> list = new Gson().fromJson(in, new TypeToken<List<Long>>() {
|
||||
}.getType());
|
||||
if (!in.nextName().equals("class")) {
|
||||
new Exception("Error: Next isn't \"class\"").printStackTrace();
|
||||
return null;
|
||||
}
|
||||
Class<T> cl;
|
||||
try {
|
||||
cl = (Class<T>) Class.forName(in.nextString());
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
LoaderCollection<T> col = new LoaderCollection<T>(cl); // TODO
|
||||
col.idlist.addAll(list);
|
||||
in.endObject();
|
||||
return col;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,23 +1,20 @@
|
|||
package io.github.norbipeti.chat.server.db.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
import io.github.norbipeti.chat.server.data.LoaderCollection;
|
||||
|
||||
@Entity
|
||||
@Table(name = "CONVERSATION")
|
||||
public class Conversation extends ChatDatabaseEntity {
|
||||
private static final long serialVersionUID = 5058682475353799722L;
|
||||
//@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;
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "conversation")
|
||||
private List<Message> messsages;
|
||||
private LoaderCollection<Message> messsages = new LoaderCollection<>(Message.class);
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
|
||||
// @JoinTable(name = "User_Conversation", joinColumns = @JoinColumn(name =
|
||||
|
@ -29,33 +26,23 @@ public class Conversation extends ChatDatabaseEntity {
|
|||
// "conversation_id", referencedColumnName = "id"), inverseJoinColumns =
|
||||
// @JoinColumn(name = "user_id", referencedColumnName = "id"))
|
||||
// @JoinTable(name = "User_Conversation")
|
||||
private Set<User> users;
|
||||
private LoaderCollection<User> users = new LoaderCollection<>(User.class);
|
||||
|
||||
public List<Message> getMesssages() {
|
||||
if (messsages == null)
|
||||
messsages = new ArrayList<>();
|
||||
public LoaderCollection<Message> getMesssages() {
|
||||
return messsages;
|
||||
}
|
||||
|
||||
public void setMesssages(List<Message> messsages) {
|
||||
public void setMesssages(LoaderCollection<Message> messsages) {
|
||||
this.messsages = messsages;
|
||||
}
|
||||
|
||||
public Set<User> getUsers() {
|
||||
if (users == null)
|
||||
users = new HashSet<>();
|
||||
public LoaderCollection<User> getUsers() {
|
||||
return users;
|
||||
}
|
||||
|
||||
public void setUsers(Set<User> users) {
|
||||
this.users = users;
|
||||
}
|
||||
|
||||
/*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; }
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
package io.github.norbipeti.chat.server.db.domain;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
import io.github.norbipeti.chat.server.data.DataManager;
|
||||
|
@ -23,7 +20,7 @@ public class User extends ChatDatabaseEntity {
|
|||
private String password;
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@OneToOne(cascade = CascadeType.ALL)
|
||||
private LoaderCollection<User> contacts;
|
||||
private LoaderCollection<User> contacts = new LoaderCollection<User>(User.class);
|
||||
private String salt;
|
||||
// @Column(columnDefinition = "CHAR(16) FOR BIT DATA")
|
||||
@Column(columnDefinition = "VARCHAR(64)")
|
||||
|
@ -36,7 +33,7 @@ public class User extends ChatDatabaseEntity {
|
|||
// @JoinColumn(referencedColumnName = "id", unique = false),
|
||||
// inverseJoinColumns = @JoinColumn(referencedColumnName = "id", unique =
|
||||
// false))
|
||||
private Set<Conversation> conversations;
|
||||
private LoaderCollection<Conversation> conversations = new LoaderCollection<>(Conversation.class);
|
||||
|
||||
/**
|
||||
* Loads all contact data
|
||||
|
@ -45,8 +42,6 @@ public class User extends ChatDatabaseEntity {
|
|||
* @throws IOException
|
||||
*/
|
||||
public List<User> getContacts() throws IOException {
|
||||
if (contacts == null)
|
||||
contacts = new LoaderCollection<User>(User.class);
|
||||
return contacts;
|
||||
}
|
||||
|
||||
|
@ -96,16 +91,10 @@ public class User extends ChatDatabaseEntity {
|
|||
this.sessionid = sessionid;
|
||||
}
|
||||
|
||||
public Set<Conversation> getConversations() {
|
||||
if (conversations == null)
|
||||
conversations = new HashSet<>();
|
||||
public LoaderCollection<Conversation> getConversations() {
|
||||
return conversations;
|
||||
}
|
||||
|
||||
public void setConversations(Set<Conversation> conversations) {
|
||||
this.conversations = conversations;
|
||||
}
|
||||
|
||||
public User() {
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ public class IndexPage extends Page {
|
|||
Element channelmessages = doc.getElementById("channelmessages");
|
||||
LogManager.getLogger().log(Level.INFO, "Conversations: " + DataManager.load(Conversation.class).size());
|
||||
LogManager.getLogger().log(Level.INFO, "User conversations: " + user.getConversations().size());
|
||||
Conversation convo = user.getConversations().iterator().next();
|
||||
Conversation convo = user.getConversations().get(0);
|
||||
LogManager.getLogger().log(Level.INFO, "Messages: " + convo.getMesssages().size());
|
||||
for (Message message : convo.getMesssages()) {
|
||||
Element msgelement = channelmessages.appendElement("div");
|
||||
|
|
|
@ -2,8 +2,6 @@ package io.github.norbipeti.chat.server.page;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import com.google.gson.JsonObject;
|
||||
|
@ -11,6 +9,7 @@ import com.sun.net.httpserver.HttpExchange;
|
|||
|
||||
import io.github.norbipeti.chat.server.IOHelper;
|
||||
import io.github.norbipeti.chat.server.data.DataManager;
|
||||
import io.github.norbipeti.chat.server.data.LoaderCollection;
|
||||
import io.github.norbipeti.chat.server.db.domain.Conversation;
|
||||
import io.github.norbipeti.chat.server.db.domain.Message;
|
||||
import io.github.norbipeti.chat.server.db.domain.User;
|
||||
|
@ -49,7 +48,7 @@ public class MessageAjaxPage extends Page {
|
|||
IOHelper.SendResponse(400, "<h1>400 Bad request</h1><p>The message cannot be empty,</p>", exchange);
|
||||
return;
|
||||
}
|
||||
Set<Conversation> convos = user.getConversations();
|
||||
LoaderCollection<Conversation> convos = user.getConversations();
|
||||
Conversation conv = null;
|
||||
LogManager.getLogger().log(Level.DEBUG, "Len: " + convos.size());
|
||||
for (Conversation con : convos) {
|
||||
|
|
Loading…
Reference in a new issue