Working on generalizing the serializers
This commit is contained in:
parent
88733223c6
commit
d6834c2ae4
9 changed files with 82 additions and 36 deletions
|
@ -4,6 +4,11 @@
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
var cmsgs = document.getElementById("channelmessages");
|
var cmsgs = document.getElementById("channelmessages");
|
||||||
if (cmsgs != null && cmsgs.childElementCount > 0)
|
if (cmsgs != null && cmsgs.childElementCount > 0) {
|
||||||
|
cmsgs.forEach(function (item) {
|
||||||
|
var ctime = item.getElementById("converttime");
|
||||||
|
ctime.innerText = new Date(ctime.innerText * 1).toDateString();
|
||||||
|
});
|
||||||
cmsgs.lastElementChild.scrollIntoView(false);
|
cmsgs.lastElementChild.scrollIntoView(false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,9 +16,9 @@ import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.sun.net.httpserver.HttpServer;
|
import com.sun.net.httpserver.HttpServer;
|
||||||
|
|
||||||
import io.github.norbipeti.chat.server.data.*;
|
import io.github.norbipeti.chat.server.data.*;
|
||||||
import io.github.norbipeti.chat.server.db.domain.*;
|
import io.github.norbipeti.chat.server.db.domain.*;
|
||||||
|
import io.github.norbipeti.chat.server.io.DataType;
|
||||||
import io.github.norbipeti.chat.server.page.*;
|
import io.github.norbipeti.chat.server.page.*;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
|
@ -31,12 +31,17 @@ public class Main {
|
||||||
LogManager.getLogger().log(Level.INFO, "Loading files...");
|
LogManager.getLogger().log(Level.INFO, "Loading files...");
|
||||||
DataManager.init();
|
DataManager.init();
|
||||||
final GsonBuilder gsonBuilder = new GsonBuilder();
|
final GsonBuilder gsonBuilder = new GsonBuilder();
|
||||||
gsonBuilder.registerTypeAdapter(new TypeToken<LoaderCollection<Conversation>>() {
|
Reflections rf = new Reflections(
|
||||||
}.getType(), new LoaderCollectionSerializer<Conversation>());
|
new ConfigurationBuilder().setUrls(ClasspathHelper.forClassLoader(SavedData.class.getClassLoader()))
|
||||||
gsonBuilder.registerTypeAdapter(new TypeToken<LoaderCollection<MessageChunk>>() {
|
.addClassLoader(SavedData.class.getClassLoader()).addScanners(new SubTypesScanner())
|
||||||
}.getType(), new LoaderCollectionSerializer<MessageChunk>());
|
.filterInputsBy((String pkg) -> pkg.contains(SavedData.class.getPackage().getName())));
|
||||||
gsonBuilder.registerTypeAdapter(new TypeToken<LoaderCollection<User>>() {
|
Set<Class<? extends SavedData>> datas = rf.getSubTypesOf(SavedData.class);
|
||||||
}.getType(), new LoaderCollectionSerializer<User>());
|
for (Class<? extends SavedData> data : datas) {
|
||||||
|
if (Modifier.isAbstract(data.getModifiers()))
|
||||||
|
continue;
|
||||||
|
gsonBuilder.registerTypeAdapter(new DataType(LoaderCollection.class, data),
|
||||||
|
new LoaderCollectionSerializer()); // TODO: Test
|
||||||
|
}
|
||||||
gsonBuilder.registerTypeAdapter(new TypeToken<LoaderRef<Conversation>>() {
|
gsonBuilder.registerTypeAdapter(new TypeToken<LoaderRef<Conversation>>() {
|
||||||
}.getType(), new LoaderRefSerializer<Conversation>());
|
}.getType(), new LoaderRefSerializer<Conversation>());
|
||||||
gsonBuilder.registerTypeAdapter(new TypeToken<LoaderRef<MessageChunk>>() {
|
gsonBuilder.registerTypeAdapter(new TypeToken<LoaderRef<MessageChunk>>() {
|
||||||
|
@ -58,10 +63,10 @@ public class Main {
|
||||||
*/
|
*/
|
||||||
LogManager.getLogger().log(Level.INFO, "Starting webserver..."); // TODO: Separate IDs for conversations and users
|
LogManager.getLogger().log(Level.INFO, "Starting webserver..."); // TODO: Separate IDs for conversations and users
|
||||||
HttpServer server = HttpServer.create(new InetSocketAddress(InetAddress.getLocalHost(), 8080), 10);
|
HttpServer server = HttpServer.create(new InetSocketAddress(InetAddress.getLocalHost(), 8080), 10);
|
||||||
Reflections rf = new Reflections(
|
rf = new Reflections(
|
||||||
new ConfigurationBuilder().setUrls(ClasspathHelper.forClassLoader(Page.class.getClassLoader()))
|
new ConfigurationBuilder().setUrls(ClasspathHelper.forClassLoader(Page.class.getClassLoader()))
|
||||||
.addClassLoader(Page.class.getClassLoader()).addScanners(new SubTypesScanner())
|
.addClassLoader(Page.class.getClassLoader()).addScanners(new SubTypesScanner())
|
||||||
.filterInputsBy((String pkg) -> pkg.contains("io.github.norbipeti.chat.server.page")));
|
.filterInputsBy((String pkg) -> pkg.contains(Page.class.getPackage().getName())));
|
||||||
Set<Class<? extends Page>> pages = rf.getSubTypesOf(Page.class);
|
Set<Class<? extends Page>> pages = rf.getSubTypesOf(Page.class);
|
||||||
for (Class<? extends Page> page : pages) {
|
for (Class<? extends Page> page : pages) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -61,7 +61,7 @@ public final class DataManager {
|
||||||
private static <T extends SavedData> T loadFromFile(File file, Class<T> cl) {
|
private static <T extends SavedData> T loadFromFile(File file, Class<T> cl) {
|
||||||
try {
|
try {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
T obj = cl.newInstance();
|
T obj = SavedData.create(cl);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
if (cache.containsKey(file))
|
if (cache.containsKey(file))
|
||||||
|
@ -146,7 +146,7 @@ public final class DataManager {
|
||||||
File file = new File("data", "idlist.ini");
|
File file = new File("data", "idlist.ini");
|
||||||
String contents = "";
|
String contents = "";
|
||||||
for (Entry<Class<? extends SavedData>, Long> item : ids.entrySet()) {
|
for (Entry<Class<? extends SavedData>, Long> item : ids.entrySet()) {
|
||||||
contents += item.getKey().getName() + "=" + item.getValue() + "\n";
|
contents += item.getKey().getSimpleName() + "=" + item.getValue() + "\n";
|
||||||
}
|
}
|
||||||
Files.write(contents, file, StandardCharsets.UTF_8);
|
Files.write(contents, file, StandardCharsets.UTF_8);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ import io.github.norbipeti.chat.server.db.domain.SavedData;
|
||||||
*
|
*
|
||||||
* @param <T>
|
* @param <T>
|
||||||
*/
|
*/
|
||||||
public class LoaderCollection<T extends SavedData> implements List<T>, Serializable {
|
public class LoaderCollection<T extends SavedData> extends Loader implements List<T> {
|
||||||
private static final long serialVersionUID = 5426152406394894301L;
|
private static final long serialVersionUID = 5426152406394894301L;
|
||||||
List<Long> idlist;
|
List<Long> idlist;
|
||||||
Class<T> cl;
|
Class<T> cl;
|
||||||
|
@ -32,6 +32,7 @@ public class LoaderCollection<T extends SavedData> implements List<T>, Serializa
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public LoaderCollection() {
|
public LoaderCollection() {
|
||||||
|
idlist = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoaderCollection(Class<T> cl) {
|
public LoaderCollection(Class<T> cl) {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package io.github.norbipeti.chat.server.data;
|
package io.github.norbipeti.chat.server.data;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -15,15 +17,16 @@ import io.github.norbipeti.chat.server.db.domain.SavedData;
|
||||||
|
|
||||||
// @SuppressWarnings("rawtypes")
|
// @SuppressWarnings("rawtypes")
|
||||||
public class LoaderCollectionSerializer extends TypeAdapter<LoaderCollection<?>> {
|
public class LoaderCollectionSerializer extends TypeAdapter<LoaderCollection<?>> {
|
||||||
private static final Type returnType = getReturnType();
|
// private static final Type returnType = getReturnType();
|
||||||
|
|
||||||
|
// TODO: http://stackoverflow.com/a/17300227
|
||||||
@Override
|
@Override
|
||||||
public void write(JsonWriter out, LoaderCollection<?> value) throws IOException {
|
public void write(JsonWriter out, LoaderCollection<?> value) throws IOException {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.nullValue();
|
out.nullValue();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
out.beginObject(); // TODO: http://stackoverflow.com/a/17300227
|
out.beginObject();
|
||||||
out.name("items");
|
out.name("items");
|
||||||
new Gson().toJson(value.idlist, new TypeToken<List<Long>>() {
|
new Gson().toJson(value.idlist, new TypeToken<List<Long>>() {
|
||||||
}.getType(), out);
|
}.getType(), out);
|
||||||
|
@ -33,7 +36,7 @@ public class LoaderCollectionSerializer extends TypeAdapter<LoaderCollection<?>>
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public LoaderCollection<T> read(JsonReader in) throws IOException {
|
public LoaderCollection<? extends SavedData> read(JsonReader in) throws IOException {
|
||||||
if (in.peek().equals(JsonToken.NULL)) {
|
if (in.peek().equals(JsonToken.NULL)) {
|
||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
|
@ -46,25 +49,27 @@ public class LoaderCollectionSerializer extends TypeAdapter<LoaderCollection<?>>
|
||||||
new Exception("Error: Next isn't \"class\"").printStackTrace();
|
new Exception("Error: Next isn't \"class\"").printStackTrace();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Class<T> cl;
|
Class<? extends SavedData> cl;
|
||||||
try {
|
try {
|
||||||
cl = (Class<T>) Class.forName(DataManager.getPackageName() + "." + in.nextString());
|
cl = (Class<? extends SavedData>) Class.forName(DataManager.getPackageName() + "." + in.nextString());
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
LoaderCollection<T> col = new LoaderCollection<T>(cl);
|
LoaderCollection<? extends SavedData> col;
|
||||||
|
try {
|
||||||
|
col = LoaderCollection.class.getDeclaredConstructor(Class.class).newInstance(cl);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
col.idlist.addAll(list);
|
col.idlist.addAll(list);
|
||||||
in.endObject();
|
in.endObject();
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Type getReturnType() {
|
/*
|
||||||
try {
|
* private static Type getReturnType() { try { for (Method m : LoaderCollection.class.getDeclaredMethods()) System.out.println(m); return LoaderCollection.class.getDeclaredMethod("get",
|
||||||
return LoaderCollection.class.getDeclaredMethod("get", Integer.class).getGenericReturnType();
|
* int.class).getGenericReturnType(); } catch (Exception e) { e.printStackTrace(); } return null; }
|
||||||
} catch (Exception e) {
|
*/
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,19 +6,16 @@ import io.github.norbipeti.chat.server.db.domain.SavedData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* This class will only store IDs and load the object when calling
|
* This class will only store IDs and load the object when calling {@link #get()}
|
||||||
* {@link #get()}
|
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* And will also only save IDs when serialized with {@link LoaderRefSerializer}
|
* And will also only save IDs when serialized with {@link LoaderRefSerializer}
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Norbi
|
* @author Norbi
|
||||||
*
|
* @param <T> The type of the stored object
|
||||||
* @param <T>
|
|
||||||
* The type of the stored object
|
|
||||||
*/
|
*/
|
||||||
public class LoaderRef<T extends SavedData> implements Serializable {
|
public class LoaderRef<T extends SavedData> extends Loader {
|
||||||
private static final long serialVersionUID = 8458570738734235320L;
|
private static final long serialVersionUID = 8458570738734235320L;
|
||||||
Class<T> cl;
|
Class<T> cl;
|
||||||
Long id;
|
Long id;
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class LoaderRefSerializer<T extends SavedData> extends TypeAdapter<Loader
|
||||||
in.nextName();
|
in.nextName();
|
||||||
long id = in.nextLong();
|
long id = in.nextLong();
|
||||||
if (!in.nextName().equals("class")) {
|
if (!in.nextName().equals("class")) {
|
||||||
new Exception("Error: Next isn't \"class\"").printStackTrace();
|
new Exception("Error: Next isn't \"class\"").printStackTrace(); // TODO: Same as at LoaderCollectionSerializer
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Class<T> cl;
|
Class<T> cl;
|
||||||
|
|
32
src/io/github/norbipeti/chat/server/io/DataType.java
Normal file
32
src/io/github/norbipeti/chat/server/io/DataType.java
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package io.github.norbipeti.chat.server.io;
|
||||||
|
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import io.github.norbipeti.chat.server.data.Loader;
|
||||||
|
import io.github.norbipeti.chat.server.db.domain.SavedData;
|
||||||
|
|
||||||
|
public final class DataType implements ParameterizedType {
|
||||||
|
private Class<? extends SavedData> datacl;
|
||||||
|
private Class<? extends Loader> loadercl;
|
||||||
|
|
||||||
|
public DataType(Class<? extends Loader> loadercl, Class<? extends SavedData> datacl) {
|
||||||
|
this.datacl = datacl;
|
||||||
|
this.loadercl = loadercl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type[] getActualTypeArguments() {
|
||||||
|
return new Type[] { datacl };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getRawType() {
|
||||||
|
return loadercl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getOwnerType() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,9 +61,10 @@ public class IndexPage extends Page {
|
||||||
for (Message message : chunk.getMessages()) {
|
for (Message message : chunk.getMessages()) {
|
||||||
Element msgelement = channelmessages.appendElement("div");
|
Element msgelement = channelmessages.appendElement("div");
|
||||||
Element header = msgelement.appendElement("p");
|
Element header = msgelement.appendElement("p");
|
||||||
header.text(message.getSender().get().getName() + " - " + message.getTime());
|
header.text(message.getSender().get().getName() + " - <span id=\"converttime\">"
|
||||||
|
+ message.getTime().getTime() + "</span>");
|
||||||
Element body = msgelement.appendElement("p");
|
Element body = msgelement.appendElement("p");
|
||||||
body.text(message.getMessage());
|
body.text(message.getMessage()); // TODO: Use JavaScript to convert time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return doc;
|
return doc;
|
||||||
|
|
Loading…
Reference in a new issue