From e09865e7b3b0931b4ed2d1316d8bfadabe56ba6b Mon Sep 17 00:00:00 2001
From: tobias <thinkdifferent055@gmail.com>
Date: Sun, 29 Oct 2017 14:08:08 +0100
Subject: [PATCH] Add json serializer and deserializer

---
 .../playpad/server/json/JsonCollection.java   |  18 +++
 .../tobias/playpad/server/json/JsonName.java  |  18 +++
 .../tobias/playpad/server/json/JsonObj.java   |  17 +++
 .../playpad/server/json/JsonParent.java       |   9 ++
 .../playpad/server/json/JsonSerializer.scala  | 113 ++++++++++++++++++
 .../server/json/NumberSerializerHandler.scala |  15 +++
 .../server/json/SerializerHandler.scala       |   9 ++
 .../server/json/StringSerializerHandler.scala |  15 +++
 .../server/json/UUIDSerializerHandler.scala   |  17 +++
 .../playpad/server/project/Design.scala       |   6 +
 .../tobias/playpad/server/project/Pad.scala   |  10 ++
 .../tobias/playpad/server/project/Page.scala  |   8 ++
 .../tobias/playpad/server/project/Path.scala  |   5 +
 .../playpad/server/project/Project.scala      |  14 ++-
 .../server/project/ProjectReference.scala     |  17 ---
 .../project/loader/json/DesignLoader.scala    |  23 ----
 .../project/loader/json/PadLoader.scala       |  43 -------
 .../project/loader/json/PageLoader.scala      |  32 -----
 .../project/loader/json/PathLoader.scala      |  29 -----
 .../project/loader/json/ProjectLoader.scala   |  23 ----
 .../project/loader/sql/PageLoader.scala       |   2 +-
 .../project/loader/sql/ProjectLoader.scala    |  32 +++--
 .../project/saver/json/DesignSaver.scala      |  20 ----
 .../server/project/saver/json/PadSaver.scala  |  30 -----
 .../server/project/saver/json/PageSaver.scala |  25 ----
 .../server/project/saver/json/PathSaver.scala |  19 ---
 .../project/saver/json/ProjectSaver.scala     |  24 ----
 .../server/project/saver/sql/PageSaver.scala  |   2 +-
 .../project/saver/sql/ProjectSaver.scala      |   5 +-
 .../playpad/server/server/SqlHelper.scala     |   8 +-
 .../server/server/project/ProjectGet.scala    |   7 +-
 .../server/server/project/ProjectPost.scala   |  11 +-
 .../project/sync/ProjectSyncHandler.scala     |  10 +-
 33 files changed, 309 insertions(+), 327 deletions(-)
 create mode 100644 src/main/java/de/tobias/playpad/server/json/JsonCollection.java
 create mode 100644 src/main/java/de/tobias/playpad/server/json/JsonName.java
 create mode 100644 src/main/java/de/tobias/playpad/server/json/JsonObj.java
 create mode 100644 src/main/java/de/tobias/playpad/server/json/JsonParent.java
 create mode 100644 src/main/scala/de/tobias/playpad/server/json/JsonSerializer.scala
 create mode 100644 src/main/scala/de/tobias/playpad/server/json/NumberSerializerHandler.scala
 create mode 100644 src/main/scala/de/tobias/playpad/server/json/SerializerHandler.scala
 create mode 100644 src/main/scala/de/tobias/playpad/server/json/StringSerializerHandler.scala
 create mode 100644 src/main/scala/de/tobias/playpad/server/json/UUIDSerializerHandler.scala
 delete mode 100644 src/main/scala/de/tobias/playpad/server/project/ProjectReference.scala
 delete mode 100644 src/main/scala/de/tobias/playpad/server/project/loader/json/DesignLoader.scala
 delete mode 100644 src/main/scala/de/tobias/playpad/server/project/loader/json/PadLoader.scala
 delete mode 100644 src/main/scala/de/tobias/playpad/server/project/loader/json/PageLoader.scala
 delete mode 100644 src/main/scala/de/tobias/playpad/server/project/loader/json/PathLoader.scala
 delete mode 100644 src/main/scala/de/tobias/playpad/server/project/loader/json/ProjectLoader.scala
 delete mode 100644 src/main/scala/de/tobias/playpad/server/project/saver/json/DesignSaver.scala
 delete mode 100644 src/main/scala/de/tobias/playpad/server/project/saver/json/PadSaver.scala
 delete mode 100644 src/main/scala/de/tobias/playpad/server/project/saver/json/PageSaver.scala
 delete mode 100644 src/main/scala/de/tobias/playpad/server/project/saver/json/PathSaver.scala
 delete mode 100644 src/main/scala/de/tobias/playpad/server/project/saver/json/ProjectSaver.scala

diff --git a/src/main/java/de/tobias/playpad/server/json/JsonCollection.java b/src/main/java/de/tobias/playpad/server/json/JsonCollection.java
new file mode 100644
index 0000000..e6e8dcc
--- /dev/null
+++ b/src/main/java/de/tobias/playpad/server/json/JsonCollection.java
@@ -0,0 +1,18 @@
+package de.tobias.playpad.server.json;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface JsonCollection {
+
+	/**
+	 * Name of the field for the json.
+	 *
+	 * @return name
+	 */
+	String value();
+
+	Class type();
+}
diff --git a/src/main/java/de/tobias/playpad/server/json/JsonName.java b/src/main/java/de/tobias/playpad/server/json/JsonName.java
new file mode 100644
index 0000000..464aaf3
--- /dev/null
+++ b/src/main/java/de/tobias/playpad/server/json/JsonName.java
@@ -0,0 +1,18 @@
+package de.tobias.playpad.server.json;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface JsonName {
+
+	/**
+	 * Name of the field for the json.
+	 *
+	 * @return name
+	 */
+	String value();
+
+	Class<? extends SerializerHandler> handler() default StringSerializerHandler.class;
+}
diff --git a/src/main/java/de/tobias/playpad/server/json/JsonObj.java b/src/main/java/de/tobias/playpad/server/json/JsonObj.java
new file mode 100644
index 0000000..5f49aed
--- /dev/null
+++ b/src/main/java/de/tobias/playpad/server/json/JsonObj.java
@@ -0,0 +1,17 @@
+package de.tobias.playpad.server.json;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface JsonObj {
+
+	/**
+	 * Name of the field for the json.
+	 *
+	 * @return name
+	 */
+	String value();
+
+}
diff --git a/src/main/java/de/tobias/playpad/server/json/JsonParent.java b/src/main/java/de/tobias/playpad/server/json/JsonParent.java
new file mode 100644
index 0000000..d01a649
--- /dev/null
+++ b/src/main/java/de/tobias/playpad/server/json/JsonParent.java
@@ -0,0 +1,9 @@
+package de.tobias.playpad.server.json;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface JsonParent {
+}
diff --git a/src/main/scala/de/tobias/playpad/server/json/JsonSerializer.scala b/src/main/scala/de/tobias/playpad/server/json/JsonSerializer.scala
new file mode 100644
index 0000000..5683dde
--- /dev/null
+++ b/src/main/scala/de/tobias/playpad/server/json/JsonSerializer.scala
@@ -0,0 +1,113 @@
+package de.tobias.playpad.server.json
+
+import java.util
+
+import com.google.gson.{JsonArray, JsonObject}
+
+class JsonSerializer {
+
+	def serialize(o: Any): JsonObject = {
+		val jsonObject = new JsonObject
+		o.getClass.getDeclaredFields
+			.filter(f => f.isAnnotationPresent(classOf[JsonName]))
+			.foreach(f => {
+				f.setAccessible(true)
+				val annotation = f.getAnnotation(classOf[JsonName])
+				val value = f.get(o)
+				if (value != null) {
+					jsonObject.add(annotation.value(), annotation.handler().newInstance().serialize(value))
+				}
+			})
+
+		o.getClass.getDeclaredFields
+			.filter(f => f.isAnnotationPresent(classOf[JsonObj]))
+			.foreach(f => {
+				f.setAccessible(true)
+				val annotation = f.getAnnotation(classOf[JsonObj])
+				val value = f.get(o)
+				if (value != null) {
+					jsonObject.add(annotation.value(), serialize(value))
+				}
+			})
+
+		o.getClass.getDeclaredFields
+			.filter(f => f.isAnnotationPresent(classOf[JsonCollection]))
+			.foreach(f => {
+				f.setAccessible(true)
+				val annotation = f.getAnnotation(classOf[JsonCollection])
+				val value = f.get(o)
+
+				val jsonValues = value match {
+					case seq: Seq[_] => seq.map(serialize)
+				}
+				val jsonArray = new JsonArray(jsonValues.size)
+				jsonValues.foreach(jsonArray.add)
+				jsonObject.add(annotation.value(), jsonArray)
+			})
+
+		jsonObject
+	}
+
+	def deserialize[T](jsonObject: JsonObject, clazz: Class[T]): T = {
+		val obj = clazz.newInstance()
+
+		clazz.getDeclaredFields
+			.filter(f => f.isAnnotationPresent(classOf[JsonName]))
+			.foreach(f => {
+				println(clazz + "\t" + f.getName)
+				f.setAccessible(true)
+				val annotation = f.getAnnotation(classOf[JsonName])
+				val value = jsonObject.get(annotation.value())
+				f.set(obj, annotation.handler().newInstance().deserialize(value))
+			})
+
+
+		clazz.getDeclaredFields
+			.filter(f => f.isAnnotationPresent(classOf[JsonObj]))
+			.foreach(f => {
+				f.setAccessible(true)
+				val annotation = f.getAnnotation(classOf[JsonObj])
+				val jsonObj = jsonObject.getAsJsonObject(annotation.value())
+				val value = if (jsonObj != null) {
+					val value = deserialize(jsonObj, f.getType)
+					setParent(value, obj)
+					value
+				} else {
+					null
+				}
+				f.set(obj, value)
+			})
+
+		clazz.getDeclaredFields
+			.filter(f => f.isAnnotationPresent(classOf[JsonCollection]))
+			.foreach(f => {
+				f.setAccessible(true)
+				val annotation = f.getAnnotation(classOf[JsonCollection])
+				val jsonArray = jsonObject.getAsJsonArray(annotation.value())
+
+				val tempList = new util.ArrayList[Any]()
+				jsonArray.forEach(elem => {
+					val value = deserialize(elem.getAsJsonObject, annotation.`type`())
+					setParent(value, obj)
+					tempList.add(value)
+				})
+
+				var col = f.get(obj)
+				col match {
+					case _: List[_] => tempList.forEach(e => col = e :: col.asInstanceOf[List[_]])
+				}
+				f.set(obj, col)
+			})
+
+		obj
+	}
+
+	private def setParent(value: Any, parent: Any): Unit = {
+		value.getClass.getDeclaredFields
+			.filter(f => f.isAnnotationPresent(classOf[JsonParent]))
+			.foreach(f => {
+				f.setAccessible(true)
+				f.set(value, parent)
+			})
+	}
+}
diff --git a/src/main/scala/de/tobias/playpad/server/json/NumberSerializerHandler.scala b/src/main/scala/de/tobias/playpad/server/json/NumberSerializerHandler.scala
new file mode 100644
index 0000000..1e860fb
--- /dev/null
+++ b/src/main/scala/de/tobias/playpad/server/json/NumberSerializerHandler.scala
@@ -0,0 +1,15 @@
+package de.tobias.playpad.server.json
+
+import com.google.gson.{JsonElement, JsonPrimitive}
+
+class NumberSerializerHandler extends SerializerHandler {
+	override def serialize(value: Any): JsonPrimitive = value match {
+		case number: Number => new JsonPrimitive(number)
+		case _ => null
+	}
+
+	override def deserialize(jsonElement: JsonElement): Number = jsonElement match {
+		case jsonPrimitive: JsonPrimitive => jsonPrimitive.getAsInt
+		case _ => null
+	}
+}
diff --git a/src/main/scala/de/tobias/playpad/server/json/SerializerHandler.scala b/src/main/scala/de/tobias/playpad/server/json/SerializerHandler.scala
new file mode 100644
index 0000000..1f4d1b2
--- /dev/null
+++ b/src/main/scala/de/tobias/playpad/server/json/SerializerHandler.scala
@@ -0,0 +1,9 @@
+package de.tobias.playpad.server.json
+
+import com.google.gson.{JsonElement, JsonPrimitive}
+
+trait SerializerHandler {
+	def serialize(value: Any): JsonPrimitive
+
+	def deserialize(jsonElement: JsonElement): Any
+}
diff --git a/src/main/scala/de/tobias/playpad/server/json/StringSerializerHandler.scala b/src/main/scala/de/tobias/playpad/server/json/StringSerializerHandler.scala
new file mode 100644
index 0000000..6d99562
--- /dev/null
+++ b/src/main/scala/de/tobias/playpad/server/json/StringSerializerHandler.scala
@@ -0,0 +1,15 @@
+package de.tobias.playpad.server.json
+
+import com.google.gson.{JsonElement, JsonPrimitive}
+
+class StringSerializerHandler extends SerializerHandler {
+	override def serialize(value: Any): JsonPrimitive = value match {
+		case str: String => new JsonPrimitive(str)
+		case _ => null
+	}
+
+	override def deserialize(jsonElement: JsonElement): String = jsonElement match {
+		case jsonPrimitive: JsonPrimitive => jsonPrimitive.getAsString
+		case _ => null
+	}
+}
diff --git a/src/main/scala/de/tobias/playpad/server/json/UUIDSerializerHandler.scala b/src/main/scala/de/tobias/playpad/server/json/UUIDSerializerHandler.scala
new file mode 100644
index 0000000..51afb49
--- /dev/null
+++ b/src/main/scala/de/tobias/playpad/server/json/UUIDSerializerHandler.scala
@@ -0,0 +1,17 @@
+package de.tobias.playpad.server.json
+
+import java.util.UUID
+
+import com.google.gson.{JsonElement, JsonPrimitive}
+
+class UUIDSerializerHandler extends SerializerHandler {
+	override def serialize(value: Any): JsonPrimitive = value match {
+		case uuid: UUID => new JsonPrimitive(uuid.toString)
+		case _ => null
+	}
+
+	override def deserialize(jsonElement: JsonElement): UUID = jsonElement match {
+		case jsonPrimitive: JsonPrimitive => UUID.fromString(jsonPrimitive.getAsString)
+		case _ => null
+	}
+}
diff --git a/src/main/scala/de/tobias/playpad/server/project/Design.scala b/src/main/scala/de/tobias/playpad/server/project/Design.scala
index 0dc6abb..c3b6644 100644
--- a/src/main/scala/de/tobias/playpad/server/project/Design.scala
+++ b/src/main/scala/de/tobias/playpad/server/project/Design.scala
@@ -2,14 +2,20 @@ package de.tobias.playpad.server.project
 
 import java.util.UUID
 
+import de.tobias.playpad.server.json.{JsonName, JsonParent, UUIDSerializerHandler}
+
 /**
   * Created by tobias on 23.02.17.
   */
 class Design {
 
+	@JsonName(value = "id", handler = classOf[UUIDSerializerHandler])
 	var id: UUID = UUID.randomUUID()
+	@JsonName("background_color")
 	var backgroundColor: String = _
+	@JsonName("play_color")
 	var playColor: String = _
 
+	@JsonParent
 	var pad: Pad = _
 }
diff --git a/src/main/scala/de/tobias/playpad/server/project/Pad.scala b/src/main/scala/de/tobias/playpad/server/project/Pad.scala
index 9c4b0fc..c42bc1a 100644
--- a/src/main/scala/de/tobias/playpad/server/project/Pad.scala
+++ b/src/main/scala/de/tobias/playpad/server/project/Pad.scala
@@ -2,19 +2,29 @@ package de.tobias.playpad.server.project
 
 import java.util.UUID
 
+import de.tobias.playpad.server.json._
+
 /**
   * Created by tobias on 17.02.17.
   */
 class Pad() {
 
+	@JsonName(value = "id", handler = classOf[UUIDSerializerHandler])
 	var id: UUID = UUID.randomUUID()
+
+	@JsonName("name")
 	var name: String = _
+	@JsonName(value = "position", handler = classOf[NumberSerializerHandler])
 	var position: Int = _
 
+	@JsonName("contentType")
 	var contentType: String = _
+	@JsonCollection(value = "paths", `type` = classOf[Path])
 	var paths: List[Path] = List()
 
+	@JsonObj("design")
 	var design: Design = _
 
+	@JsonParent
 	var page: Page = _
 }
diff --git a/src/main/scala/de/tobias/playpad/server/project/Page.scala b/src/main/scala/de/tobias/playpad/server/project/Page.scala
index 079602a..76236fa 100644
--- a/src/main/scala/de/tobias/playpad/server/project/Page.scala
+++ b/src/main/scala/de/tobias/playpad/server/project/Page.scala
@@ -2,16 +2,24 @@ package de.tobias.playpad.server.project
 
 import java.util.UUID
 
+import de.tobias.playpad.server.json._
+
 /**
   * Created by tobias on 17.02.17.
   */
 class Page {
 
+	@JsonName(value = "id", handler = classOf[UUIDSerializerHandler])
 	var id: UUID = UUID.randomUUID()
+	@JsonName("name")
 	var name: String = _
 
+	@JsonName(value = "position", handler = classOf[NumberSerializerHandler])
 	var position: Int = _
 
+	@JsonCollection(value = "pads", `type` = classOf[Pad])
 	var pads: List[Pad] = List()
+
+	@JsonParent
 	var project: Project = _ // FOREIGN KEY
 }
diff --git a/src/main/scala/de/tobias/playpad/server/project/Path.scala b/src/main/scala/de/tobias/playpad/server/project/Path.scala
index 1e8c2b0..467de17 100644
--- a/src/main/scala/de/tobias/playpad/server/project/Path.scala
+++ b/src/main/scala/de/tobias/playpad/server/project/Path.scala
@@ -2,13 +2,18 @@ package de.tobias.playpad.server.project
 
 import java.util.UUID
 
+import de.tobias.playpad.server.json.{JsonName, JsonParent, UUIDSerializerHandler}
+
 /**
   * Created by tobias on 20.02.17.
   */
 class Path {
 
+	@JsonName(value = "id", handler = classOf[UUIDSerializerHandler])
 	var id: UUID = UUID.randomUUID()
+	@JsonName("filename")
 	var filename: String = _
 
+	@JsonParent
 	var pad: Pad = _
 }
diff --git a/src/main/scala/de/tobias/playpad/server/project/Project.scala b/src/main/scala/de/tobias/playpad/server/project/Project.scala
index 7cd0475..fc28a98 100644
--- a/src/main/scala/de/tobias/playpad/server/project/Project.scala
+++ b/src/main/scala/de/tobias/playpad/server/project/Project.scala
@@ -2,15 +2,23 @@ package de.tobias.playpad.server.project
 
 import java.util.UUID
 
-import de.tobias.playpad.server.account.Session
+import de.tobias.playpad.server.json.{JsonCollection, JsonName, UUIDSerializerHandler}
 
 /**
   * Created by tobias on 17.02.17.
   */
 class Project {
 
-	val projectReference = new ProjectReference
+	@JsonName(value = "id", handler = classOf[UUIDSerializerHandler])
+	var id: UUID = UUID.randomUUID()
+	@JsonName("name")
+	var name: String = _
 
-	var pages: List[Page] = _
+	var accountId: Int = _ // Account that own this project
+	var lastModified: Long = _
+	var session: String = _
+
+	@JsonCollection(value = "pages", `type` = classOf[Page])
+	var pages: List[Page] = List()
 
 }
diff --git a/src/main/scala/de/tobias/playpad/server/project/ProjectReference.scala b/src/main/scala/de/tobias/playpad/server/project/ProjectReference.scala
deleted file mode 100644
index 1d15a97..0000000
--- a/src/main/scala/de/tobias/playpad/server/project/ProjectReference.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package de.tobias.playpad.server.project
-
-import java.util.UUID
-
-/**
-  * Created by tobias on 19.02.17.
-  */
-class ProjectReference {
-
-	var id: UUID = UUID.randomUUID()
-	var name: String = _
-
-	var accountId: Int = _ // Account that own this project
-	var lastModified: Long = _
-	var session: String = _
-
-}
diff --git a/src/main/scala/de/tobias/playpad/server/project/loader/json/DesignLoader.scala b/src/main/scala/de/tobias/playpad/server/project/loader/json/DesignLoader.scala
deleted file mode 100644
index a5127e8..0000000
--- a/src/main/scala/de/tobias/playpad/server/project/loader/json/DesignLoader.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package de.tobias.playpad.server.project.loader.json
-
-import java.util.UUID
-
-import com.google.gson.JsonObject
-import de.tobias.playpad.server.project.utils.JsonDef
-import de.tobias.playpad.server.project.{Design, Pad}
-
-/**
-  * Created by tobias on 23.02.17.
-  */
-class DesignLoader {
-	def load(jsonObject: JsonObject, pad: Pad): Design = {
-		val design = new Design()
-
-		design.id = UUID.fromString(jsonObject.get(JsonDef.DESIGN_ID).getAsString)
-		design.backgroundColor = jsonObject.get(JsonDef.DESIGN_BACKGROUND_COLOR).getAsString
-		design.playColor = jsonObject.get(JsonDef.DESIGN_PLAY_COLOR).getAsString
-		design.pad = pad
-
-		design
-	}
-}
diff --git a/src/main/scala/de/tobias/playpad/server/project/loader/json/PadLoader.scala b/src/main/scala/de/tobias/playpad/server/project/loader/json/PadLoader.scala
deleted file mode 100644
index bd55a1e..0000000
--- a/src/main/scala/de/tobias/playpad/server/project/loader/json/PadLoader.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package de.tobias.playpad.server.project.loader.json
-
-import java.util.UUID
-
-import com.google.gson.{JsonArray, JsonObject}
-import de.tobias.playpad.server.project.utils.JsonDef._
-import de.tobias.playpad.server.project.{Pad, Page}
-
-import scala.collection.JavaConverters
-
-/**
-  * Created by tobias on 17.02.17.
-  */
-class PadLoader {
-	def load(jsonArray: JsonArray, page: Page): List[Pad] = {
-		val it = JavaConverters.asScalaIterator(jsonArray.iterator())
-		val pads = it.filter(_.isJsonObject).map(i => {
-			val json = i.asInstanceOf[JsonObject]
-
-			val pad = new Pad()
-			pad.id = UUID.fromString(json.get(PAD_ID).getAsString)
-			if (json.get(PAD_NAME) != null)
-				pad.name = json.get(PAD_NAME).getAsString
-			pad.position = json.get(PAD_POSITION).getAsInt
-			if (json.get(PAD_CONTENT_TYPE) != null)
-				pad.contentType = json.get(PAD_CONTENT_TYPE).getAsString
-			pad.page = page
-
-			val pathLoader = new PathLoader
-			val pathJson = json.getAsJsonArray(PAD_PATHS)
-			pad.paths = pathLoader.load(pathJson, pad)
-
-			val designLoader = new DesignLoader
-			val designJson = json.getAsJsonObject(PAD_DESIGN)
-			if (designJson != null)
-				pad.design = designLoader.load(designJson, pad)
-
-			pad
-		}).toList
-		pads
-	}
-
-}
diff --git a/src/main/scala/de/tobias/playpad/server/project/loader/json/PageLoader.scala b/src/main/scala/de/tobias/playpad/server/project/loader/json/PageLoader.scala
deleted file mode 100644
index de0a0d3..0000000
--- a/src/main/scala/de/tobias/playpad/server/project/loader/json/PageLoader.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package de.tobias.playpad.server.project.loader.json
-
-import java.util.UUID
-
-import com.google.gson.{JsonArray, JsonObject}
-import de.tobias.playpad.server.project.utils.JsonDef._
-import de.tobias.playpad.server.project.{Page, Project}
-
-import scala.collection.JavaConverters
-
-/**
-  * Created by tobias on 17.02.17.
-  */
-class PageLoader {
-	def load(jsonArray: JsonArray, project: Project): List[Page] = {
-		val it = JavaConverters.asScalaIterator(jsonArray.iterator())
-		val pages = it.filter(_.isJsonObject).map(i => {
-			val json = i.asInstanceOf[JsonObject]
-
-			val page = new Page()
-			page.id = UUID.fromString(json.get(PAGE_ID).getAsString)
-			page.name = json.get(PAGE_NAME).getAsString
-
-			val padLoader = new PadLoader
-			page.pads = padLoader.load(json.get(PAGE_PADS).getAsJsonArray, page)
-
-			page.project = project
-			page
-		}).toList
-		pages
-	}
-}
diff --git a/src/main/scala/de/tobias/playpad/server/project/loader/json/PathLoader.scala b/src/main/scala/de/tobias/playpad/server/project/loader/json/PathLoader.scala
deleted file mode 100644
index cb1a6c0..0000000
--- a/src/main/scala/de/tobias/playpad/server/project/loader/json/PathLoader.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package de.tobias.playpad.server.project.loader.json
-
-import java.util.UUID
-
-import com.google.gson.{JsonArray, JsonObject}
-import de.tobias.playpad.server.project.utils.JsonDef._
-import de.tobias.playpad.server.project.{Pad, Path}
-
-import scala.collection.JavaConverters
-
-/**
-  * Created by tobias on 20.02.17.
-  */
-class PathLoader {
-	def load(jsonArray: JsonArray, pad: Pad): List[Path] = {
-		val it = JavaConverters.asScalaIterator(jsonArray.iterator())
-		val paths = it.filter(_.isJsonObject).map(i => {
-			val json = i.asInstanceOf[JsonObject]
-
-			val path = new Path()
-			path.id = UUID.fromString(json.get(PATH_ID).getAsString)
-			path.filename = json.get(PATH_PATH).getAsString
-			path.pad = pad
-
-			path
-		}).toList
-		paths
-	}
-}
diff --git a/src/main/scala/de/tobias/playpad/server/project/loader/json/ProjectLoader.scala b/src/main/scala/de/tobias/playpad/server/project/loader/json/ProjectLoader.scala
deleted file mode 100644
index be1a394..0000000
--- a/src/main/scala/de/tobias/playpad/server/project/loader/json/ProjectLoader.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package de.tobias.playpad.server.project.loader.json
-
-import java.util.UUID
-
-import com.google.gson.JsonObject
-import de.tobias.playpad.server.project.Project
-import de.tobias.playpad.server.project.utils.JsonDef._
-
-/**
-  * Created by tobias on 17.02.17.
-  */
-class ProjectLoader {
-	def load(json: JsonObject): Project = {
-		val project = new Project()
-		project.projectReference.id = UUID.fromString(json.get(PROJECT_ID).getAsString)
-		project.projectReference.name = json.get(PROJECT_NAME).getAsString
-
-		val pageLoader = new PageLoader
-		project.pages = pageLoader.load(json.getAsJsonArray(PROJECT_PAGES), project)
-
-		project
-	}
-}
diff --git a/src/main/scala/de/tobias/playpad/server/project/loader/sql/PageLoader.scala b/src/main/scala/de/tobias/playpad/server/project/loader/sql/PageLoader.scala
index 30d44b6..7ce80fa 100644
--- a/src/main/scala/de/tobias/playpad/server/project/loader/sql/PageLoader.scala
+++ b/src/main/scala/de/tobias/playpad/server/project/loader/sql/PageLoader.scala
@@ -13,7 +13,7 @@ class PageLoader(val connection: Connection) {
 	def load(project: Project): List[Page] = {
 		val sql = s"SELECT * FROM $PAGE WHERE $PAGE_PROJECT_REF = ?"
 		val preparedStatement = connection.prepareStatement(sql)
-		preparedStatement.setString(1, project.projectReference.id.toString)
+		preparedStatement.setString(1, project.id.toString)
 		val result = preparedStatement.executeQuery()
 
 		var pages: List[Page] = List()
diff --git a/src/main/scala/de/tobias/playpad/server/project/loader/sql/ProjectLoader.scala b/src/main/scala/de/tobias/playpad/server/project/loader/sql/ProjectLoader.scala
index 24ed0a0..4775399 100644
--- a/src/main/scala/de/tobias/playpad/server/project/loader/sql/ProjectLoader.scala
+++ b/src/main/scala/de/tobias/playpad/server/project/loader/sql/ProjectLoader.scala
@@ -3,9 +3,8 @@ package de.tobias.playpad.server.project.loader.sql
 import java.sql.Connection
 import java.util.UUID
 
-import de.tobias.playpad.server.account.Session
+import de.tobias.playpad.server.project.Project
 import de.tobias.playpad.server.project.utils.SqlDef._
-import de.tobias.playpad.server.project.{Project, ProjectReference}
 
 /**
   * Created by tobias on 17.02.17.
@@ -21,12 +20,11 @@ class ProjectLoader(val connection: Connection) {
 
 		while (result.next()) {
 			val project = new Project()
-			val projectReference = project.projectReference
-			projectReference.id = UUID.fromString(result.getString(PROJECT_ID))
-			projectReference.name = result.getString(PROJECT_NAME)
-			projectReference.accountId = result.getInt(PROJECT_ACCOUNT_ID)
-			projectReference.lastModified = result.getLong(PROJECT_LAST_MODIFIED)
-			projectReference.session = result.getString(PROJECT_SESSION_KEY)
+			project.id = UUID.fromString(result.getString(PROJECT_ID))
+			project.name = result.getString(PROJECT_NAME)
+			project.accountId = result.getInt(PROJECT_ACCOUNT_ID)
+			project.lastModified = result.getLong(PROJECT_LAST_MODIFIED)
+			project.session = result.getString(PROJECT_SESSION_KEY)
 
 			val pageLoader = new PageLoader(connection)
 			project.pages = pageLoader.load(project)
@@ -40,24 +38,24 @@ class ProjectLoader(val connection: Connection) {
 		projects
 	}
 
-	def list(accountId: Int): List[ProjectReference] = {
+	def list(accountId: Int): List[Project] = {
 		val sql = s"SELECT * FROM $PROJECT WHERE $PROJECT_ACCOUNT_ID = ?"
 		val preparedStatement = connection.prepareStatement(sql)
 		preparedStatement.setInt(1, accountId)
 		val result = preparedStatement.executeQuery()
 
-		var projects: List[ProjectReference] = List()
+		var projects: List[Project] = List()
 
 		while (result.next()) {
-			val projectReference = new ProjectReference()
+			val project = new Project()
 
-			projectReference.id = UUID.fromString(result.getString(PROJECT_ID))
-			projectReference.name = result.getString(PROJECT_NAME)
-			projectReference.accountId = result.getInt(PROJECT_ACCOUNT_ID)
-			projectReference.lastModified = result.getLong(PROJECT_LAST_MODIFIED)
-			projectReference.session = result.getString(PROJECT_SESSION_KEY)
+			project.id = UUID.fromString(result.getString(PROJECT_ID))
+			project.name = result.getString(PROJECT_NAME)
+			project.accountId = result.getInt(PROJECT_ACCOUNT_ID)
+			project.lastModified = result.getLong(PROJECT_LAST_MODIFIED)
+			project.session = result.getString(PROJECT_SESSION_KEY)
 
-			projects = projectReference :: projects
+			projects = project :: projects
 		}
 
 		result.close()
diff --git a/src/main/scala/de/tobias/playpad/server/project/saver/json/DesignSaver.scala b/src/main/scala/de/tobias/playpad/server/project/saver/json/DesignSaver.scala
deleted file mode 100644
index 37144e1..0000000
--- a/src/main/scala/de/tobias/playpad/server/project/saver/json/DesignSaver.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package de.tobias.playpad.server.project.saver.json
-
-import com.google.gson.{JsonElement, JsonObject}
-import de.tobias.playpad.server.project.Design
-import de.tobias.playpad.server.project.utils.JsonDef._
-
-/**
-  * Created by tobias on 23.02.17.
-  */
-class DesignSaver {
-	def save(design: Design): JsonElement = {
-		val json = new JsonObject()
-		if (design != null) {
-			json.addProperty(DESIGN_ID, design.id.toString)
-			json.addProperty(DESIGN_BACKGROUND_COLOR, design.backgroundColor)
-			json.addProperty(DESIGN_PLAY_COLOR, design.playColor)
-		}
-		json
-	}
-}
diff --git a/src/main/scala/de/tobias/playpad/server/project/saver/json/PadSaver.scala b/src/main/scala/de/tobias/playpad/server/project/saver/json/PadSaver.scala
deleted file mode 100644
index aec2e27..0000000
--- a/src/main/scala/de/tobias/playpad/server/project/saver/json/PadSaver.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package de.tobias.playpad.server.project.saver.json
-
-import com.google.gson.{JsonArray, JsonElement, JsonObject}
-import de.tobias.playpad.server.project.Pad
-import de.tobias.playpad.server.project.utils.JsonDef._
-
-/**
-  * Created by tobias on 17.02.17.
-  */
-class PadSaver {
-	def save(pad: Pad): JsonElement = {
-		val jsonObject = new JsonObject()
-
-		val pathSaver = new PathSaver()
-		val pathArray = new JsonArray()
-		pad.paths.foreach(path => pathArray.add(pathSaver.save(path)))
-
-		val designSaver = new DesignSaver
-		val designJson = designSaver.save(pad.design)
-
-		jsonObject.addProperty(PAD_ID, pad.id.toString)
-		jsonObject.addProperty(PAD_NAME, pad.name)
-		jsonObject.addProperty(PAD_POSITION, pad.position)
-		jsonObject.addProperty(PAD_CONTENT_TYPE, pad.contentType)
-		jsonObject.add(PAD_PATHS, pathArray)
-		jsonObject.add(PAD_DESIGN, designJson)
-
-		jsonObject
-	}
-}
diff --git a/src/main/scala/de/tobias/playpad/server/project/saver/json/PageSaver.scala b/src/main/scala/de/tobias/playpad/server/project/saver/json/PageSaver.scala
deleted file mode 100644
index 883b8b6..0000000
--- a/src/main/scala/de/tobias/playpad/server/project/saver/json/PageSaver.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package de.tobias.playpad.server.project.saver.json
-
-import com.google.gson.{JsonArray, JsonElement, JsonObject}
-import de.tobias.playpad.server.project.Page
-import de.tobias.playpad.server.project.utils.JsonDef._
-
-/**
-  * Created by tobias on 17.02.17.
-  */
-class PageSaver {
-	def save(page: Page): JsonElement = {
-		val jsonObject = new JsonObject()
-
-		val padSaver = new PadSaver()
-		val padArray = new JsonArray()
-		page.pads.foreach(pad => padArray.add(padSaver.save(pad)))
-
-		jsonObject.addProperty(PAGE_ID, page.id.toString)
-		jsonObject.addProperty(PAGE_NAME, page.name)
-		jsonObject.addProperty(PAGE_POSITION, page.position)
-		jsonObject.add(PAGE_PADS, padArray)
-
-		jsonObject
-	}
-}
diff --git a/src/main/scala/de/tobias/playpad/server/project/saver/json/PathSaver.scala b/src/main/scala/de/tobias/playpad/server/project/saver/json/PathSaver.scala
deleted file mode 100644
index 7063c25..0000000
--- a/src/main/scala/de/tobias/playpad/server/project/saver/json/PathSaver.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package de.tobias.playpad.server.project.saver.json
-
-import com.google.gson.{JsonElement, JsonObject}
-import de.tobias.playpad.server.project.Path
-import de.tobias.playpad.server.project.utils.JsonDef._
-
-/**
-  * Created by tobias on 20.02.17.
-  */
-class PathSaver {
-	def save(path: Path): JsonElement = {
-		val jsonObject = new JsonObject()
-
-		jsonObject.addProperty(PATH_ID, path.id.toString)
-		jsonObject.addProperty(PATH_PATH, path.filename)
-
-		jsonObject
-	}
-}
diff --git a/src/main/scala/de/tobias/playpad/server/project/saver/json/ProjectSaver.scala b/src/main/scala/de/tobias/playpad/server/project/saver/json/ProjectSaver.scala
deleted file mode 100644
index f4b1179..0000000
--- a/src/main/scala/de/tobias/playpad/server/project/saver/json/ProjectSaver.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package de.tobias.playpad.server.project.saver.json
-
-import com.google.gson.{JsonArray, JsonObject}
-import de.tobias.playpad.server.project.Project
-import de.tobias.playpad.server.project.utils.JsonDef._
-
-/**
-  * Created by tobias on 17.02.17.
-  */
-class ProjectSaver {
-	def save(project: Project): JsonObject = {
-		val jsonObject = new JsonObject()
-
-		val pageSaver = new PageSaver()
-		val pageArray = new JsonArray
-		project.pages.foreach(page => pageArray.add(pageSaver.save(page)))
-
-		jsonObject.addProperty(PROJECT_ID, project.projectReference.id.toString)
-		jsonObject.addProperty(PROJECT_NAME, project.projectReference.name)
-		jsonObject.add(PROJECT_PAGES, pageArray)
-
-		jsonObject
-	}
-}
diff --git a/src/main/scala/de/tobias/playpad/server/project/saver/sql/PageSaver.scala b/src/main/scala/de/tobias/playpad/server/project/saver/sql/PageSaver.scala
index 1933fc6..ec28b85 100644
--- a/src/main/scala/de/tobias/playpad/server/project/saver/sql/PageSaver.scala
+++ b/src/main/scala/de/tobias/playpad/server/project/saver/sql/PageSaver.scala
@@ -13,7 +13,7 @@ class PageSaver(connection: Connection) {
 	def save(page: Page): Unit = {
 		SqlHelper.insertOrUpdate(connection, PAGE, page.id, PAGE_NAME, page.name)
 		SqlHelper.insertOrUpdate(connection, PAGE, page.id, PAGE_POSITION, page.position)
-		SqlHelper.insertOrUpdate(connection, PAGE, page.id, PAGE_PROJECT_REF, page.project.projectReference.id)
+		SqlHelper.insertOrUpdate(connection, PAGE, page.id, PAGE_PROJECT_REF, page.project.id)
 
 		val padSaver = new PadSaver(connection)
 		page.pads.foreach(padSaver.save)
diff --git a/src/main/scala/de/tobias/playpad/server/project/saver/sql/ProjectSaver.scala b/src/main/scala/de/tobias/playpad/server/project/saver/sql/ProjectSaver.scala
index 994c64c..8fcd202 100644
--- a/src/main/scala/de/tobias/playpad/server/project/saver/sql/ProjectSaver.scala
+++ b/src/main/scala/de/tobias/playpad/server/project/saver/sql/ProjectSaver.scala
@@ -12,9 +12,8 @@ import de.tobias.playpad.server.server.SqlHelper
   */
 class ProjectSaver(val connection: Connection) {
 	def save(project: Project): Unit = {
-		val reference = project.projectReference
-		SqlHelper.insertOrUpdate(connection, PROJECT, reference.id, PROJECT_NAME, reference.name)
-		SqlHelper.insertOrUpdate(connection, PROJECT, reference.id, PROJECT_ACCOUNT_ID, reference.accountId)
+		SqlHelper.insertOrUpdate(connection, PROJECT, project.id, PROJECT_NAME, project.name)
+		SqlHelper.insertOrUpdate(connection, PROJECT, project.id, PROJECT_ACCOUNT_ID, project.accountId)
 
 		val pageSaver = new PageSaver(connection)
 		project.pages.foreach(pageSaver.save)
diff --git a/src/main/scala/de/tobias/playpad/server/server/SqlHelper.scala b/src/main/scala/de/tobias/playpad/server/server/SqlHelper.scala
index a705363..790235b 100644
--- a/src/main/scala/de/tobias/playpad/server/server/SqlHelper.scala
+++ b/src/main/scala/de/tobias/playpad/server/server/SqlHelper.scala
@@ -72,7 +72,7 @@ object SqlHelper {
 	}
 
 	def createTables(connection: Connection): Unit = {
-		def createTable(sql: String) = {
+		def createTable(sql: String): Unit = {
 			val preparedStatement = connection.prepareStatement(sql)
 			preparedStatement.execute()
 			preparedStatement.close()
@@ -83,6 +83,8 @@ object SqlHelper {
 			  |  `id` varchar(48) NOT NULL DEFAULT '',
 			  |  `name` varchar(255) DEFAULT NULL,
 			  |  `account_id` int(11) DEFAULT NULL,
+			  |  `last_modified` bigint(11) DEFAULT NULL,
+			  |  `session_key` varchar(255) DEFAULT NULL,
 			  |  PRIMARY KEY (`id`),
 			  |  UNIQUE KEY `id` (`id`)
 			  |) ENGINE=InnoDB DEFAULT CHARSET=latin1;""".stripMargin)
@@ -101,7 +103,7 @@ object SqlHelper {
 			  |  `id` varchar(48) NOT NULL DEFAULT '',
 			  |  `name` varchar(255) DEFAULT NULL,
 			  |  `position` int(11) DEFAULT NULL,
-			  |  `page` int(11) DEFAULT NULL,
+			  |  `content_type` varchar(100) DEFAULT NULL,
 			  |  `page_id` varchar(48) DEFAULT NULL,
 			  |  PRIMARY KEY (`id`),
 			  |  UNIQUE KEY `id` (`id`),
@@ -110,7 +112,7 @@ object SqlHelper {
 		createTable(
 			"""CREATE TABLE IF NOT EXISTS `Path` (
 			  |  `id` varchar(40) NOT NULL DEFAULT '',
-			  |  `path` text,
+			  |  `filename` text,
 			  |  `pad_id` varchar(40) DEFAULT NULL,
 			  |  PRIMARY KEY (`id`),
 			  |  KEY `pad_id` (`pad_id`),
diff --git a/src/main/scala/de/tobias/playpad/server/server/project/ProjectGet.scala b/src/main/scala/de/tobias/playpad/server/server/project/ProjectGet.scala
index e4ca415..f11f171 100644
--- a/src/main/scala/de/tobias/playpad/server/server/project/ProjectGet.scala
+++ b/src/main/scala/de/tobias/playpad/server/server/project/ProjectGet.scala
@@ -5,8 +5,8 @@ import java.util.UUID
 
 import com.j256.ormlite.dao.Dao
 import de.tobias.playpad.server.account.Session
+import de.tobias.playpad.server.json.JsonSerializer
 import de.tobias.playpad.server.project.loader.sql.ProjectLoader
-import de.tobias.playpad.server.project.saver.json.ProjectSaver
 import de.tobias.playpad.server.server.{Result, Status}
 import spark.{Request, Response, Route}
 
@@ -28,9 +28,8 @@ class ProjectGet(connection: Connection, sessionDao: Dao[Session, Int]) extends
 
 				if (projects.size == 1) {
 					val project = projects.head
-					if (project.projectReference.accountId == s.getAccount.id) {
-						val projectSaver = new ProjectSaver()
-						return projectSaver.save(project)
+					if (project.accountId == s.getAccount.id) {
+						return new JsonSerializer().serialize(project)
 					}
 				}
 				new Result(Status.ERROR, "Project invalid")
diff --git a/src/main/scala/de/tobias/playpad/server/server/project/ProjectPost.scala b/src/main/scala/de/tobias/playpad/server/server/project/ProjectPost.scala
index 90fee85..edb831b 100644
--- a/src/main/scala/de/tobias/playpad/server/server/project/ProjectPost.scala
+++ b/src/main/scala/de/tobias/playpad/server/server/project/ProjectPost.scala
@@ -5,7 +5,8 @@ import java.sql.Connection
 import com.google.gson.JsonParser
 import com.j256.ormlite.dao.Dao
 import de.tobias.playpad.server.account.Session
-import de.tobias.playpad.server.project.loader.json.ProjectLoader
+import de.tobias.playpad.server.json.JsonSerializer
+import de.tobias.playpad.server.project.Project
 import de.tobias.playpad.server.project.saver.sql.ProjectSaver
 import de.tobias.playpad.server.server.{Result, Status}
 import spark.{Request, Response, Route}
@@ -19,13 +20,13 @@ class ProjectPost(connection: Connection, sessionDao: Dao[Session, Int]) extends
 		val session = Session.getSession(sessionKey, sessionDao)
 		session match {
 			case Some(s) =>
-				val projectParam = request.queryParams("project")
+				val projectParam = request.body()
 
 				val json = new JsonParser().parse(projectParam).getAsJsonObject
 
-				val projectLoader = new ProjectLoader
-				val project = projectLoader.load(json)
-				project.projectReference.accountId = s.getAccount.id
+				val project = new JsonSerializer().deserialize(json, classOf[Project])
+
+				project.accountId = s.getAccount.id
 
 				val projectSaver = new ProjectSaver(connection)
 				projectSaver.save(project)
diff --git a/src/main/scala/de/tobias/playpad/server/server/project/sync/ProjectSyncHandler.scala b/src/main/scala/de/tobias/playpad/server/server/project/sync/ProjectSyncHandler.scala
index 4a9b442..58b8518 100644
--- a/src/main/scala/de/tobias/playpad/server/server/project/sync/ProjectSyncHandler.scala
+++ b/src/main/scala/de/tobias/playpad/server/server/project/sync/ProjectSyncHandler.scala
@@ -94,17 +94,17 @@ import scala.collection.{Map, mutable}
 					case json: JsonObject =>
 						session match {
 							case Some(s) =>
-								val cmd = json.get("cmd").getAsString
-								if (listeners.contains(cmd)) {
-									listeners(cmd).onChange(json, connection, s)
-								}
-
 								// Write last modification to project table
 								val timeStemp = json.get("time").getAsLong
 								val projectRef = UUID.fromString(json.get("project").getAsString)
 								SqlHelper.insertOrUpdate(connection, SqlDef.PROJECT, projectRef, SqlDef.PROJECT_LAST_MODIFIED, timeStemp)
 								SqlHelper.insertOrUpdate(connection, SqlDef.PROJECT, projectRef, SqlDef.PROJECT_SESSION_KEY, s.key)
 
+								val cmd = json.get("cmd").getAsString
+								if (listeners.contains(cmd)) {
+									listeners(cmd).onChange(json, connection, s)
+								}
+
 							case None => serverSession.close(500, "Invalid Session")
 						}
 					case _ => serverSession.close(500, "Invalid Data")
-- 
GitLab