Working on generalizing the serializers

This commit is contained in:
Norbi Peti 2016-08-09 12:12:46 +02:00
parent 88733223c6
commit d6834c2ae4
9 changed files with 82 additions and 36 deletions

View file

@ -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);
}
}); });

View file

@ -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 {

View file

@ -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) {

View file

@ -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) {

View file

@ -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;
}
} }

View file

@ -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;

View file

@ -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;

View 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;
}
}

View file

@ -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;