From 3bb2ba2faedaeb097cc510295b639e2b0c0a18cd Mon Sep 17 00:00:00 2001
From: Felipe D'Abrantes <felidabrantes@gmail>
Date: Fri, 7 Apr 2023 22:59:41 +0100
Subject: [PATCH] Add a Mongo Codec for Daily objects

---
 .../feed-service/app/models/Daily.scala       | 51 +++++++++++++++++++
 .../feed-service/app/utils/MongoCodecs.scala  | 26 ++++++++++
 2 files changed, 77 insertions(+)
 create mode 100644 backend-services/feed-service/app/utils/MongoCodecs.scala

diff --git a/backend-services/feed-service/app/models/Daily.scala b/backend-services/feed-service/app/models/Daily.scala
index 1430cacc..3638ce7e 100644
--- a/backend-services/feed-service/app/models/Daily.scala
+++ b/backend-services/feed-service/app/models/Daily.scala
@@ -13,6 +13,10 @@ import java.text.SimpleDateFormat
 
 import play.api.libs.json.{Json, JsValue, JsString, JsObject, JsArray}
 
+import org.bson.{BsonWriter, BsonReader, BsonType}
+import org.bson.codecs.{Codec, EncoderContext, DecoderContext}
+import org.bson.conversions.Bson
+import org.mongodb.scala.model.Updates
 
 case class Daily(
     id: Option[ObjectId],
@@ -98,4 +102,51 @@ object Daily {
 
     def toString(daily: Daily): String =
         return s"Daily(${daily.id.toString()}, ${daily.userId.toString()}, ${daily.questionId.toString()}, ${daily.content}, ${daily.usersLiked.toString()})"
+
+    // Codec instance for serialising/deserialising type User to or from BSON.
+    // Implicit keyword lets Scala compiler automatically insert this into the code where it's needed.
+    implicit val codec: Codec[Daily] = new Codec[Daily] {
+        override def encode(writer: BsonWriter, value: Daily, encoderContext: EncoderContext): Unit = {
+            writer.writeStartDocument()
+            writer.writeObjectId("user_id", value.userId)
+            writer.writeObjectId("question_id", value.questionId)
+            writer.writeString("content", value.content)
+            writer.writeStartArray("usersLiked")
+            value.usersLiked.foreach(writer.writeObjectId)
+            writer.writeEndArray()
+            writer.writeDateTime("createdAt", value.createdAt.getTime())
+            writer.writeDateTime("updatedAt", value.updatedAt.getTime())
+            writer.writeEndDocument()
+        }
+
+        override def decode(reader: BsonReader, decoderContext: DecoderContext): Daily = {
+            reader.readStartDocument()
+            println("hi")
+            val id = reader.readObjectId("_id")
+            println(id)
+            val userId = reader.readObjectId("user_id")
+            val questionId = reader.readObjectId("question_id")
+            val content = reader.readString("content")
+            val usersLiked = {
+                reader.readName("usersLiked")
+                reader.readStartArray()
+                val buffer = collection.mutable.Buffer.empty[ObjectId]
+                while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
+                    buffer += reader.readObjectId()
+                }
+                reader.readEndArray()
+                buffer.toSeq
+            }
+            val createdAt = reader.readDateTime("createdAt")
+            val updatedAt = reader.readDateTime("updatedAt")
+            reader.readEndDocument()
+
+            val createdAtDate: Date = Date.from(Instant.ofEpochMilli(createdAt))
+            val updatedAtDate: Date = Date.from(Instant.ofEpochMilli(updatedAt))
+
+            Daily(Some(id), userId, questionId, content, usersLiked, createdAtDate, updatedAtDate)
+        }
+
+        override def getEncoderClass: Class[Daily] = classOf[Daily]
+    }
 }
diff --git a/backend-services/feed-service/app/utils/MongoCodecs.scala b/backend-services/feed-service/app/utils/MongoCodecs.scala
new file mode 100644
index 00000000..f755d934
--- /dev/null
+++ b/backend-services/feed-service/app/utils/MongoCodecs.scala
@@ -0,0 +1,26 @@
+package utils
+
+import models.Daily
+import org.bson.codecs.Codec
+import org.bson.codecs.configuration.{CodecProvider, CodecRegistry, CodecRegistries}
+
+import org.mongodb.scala.MongoClient
+
+object MongoCodecs {
+    // Define a custom CodecProvider that returns a Codec for the case classes
+    val customCodecProvider = new CodecProvider {
+        override def get[T](clazz: Class[T], registry: CodecRegistry): Codec[T] = {
+            if (clazz == classOf[Daily]) {
+                // If the class is the Daily case class, return the Daily codec
+                Daily.codec.asInstanceOf[Codec[T]]
+            }
+            else {
+                // If the class is not the User case class, return null
+                null
+            }
+        }
+    }
+
+    // Create a CodecRegistry that includes the custom CodecProvider and the default codecs
+    val codecRegistry: CodecRegistry = CodecRegistries.fromProviders(customCodecProvider, MongoClient.DEFAULT_CODEC_REGISTRY)
+}
-- 
GitLab