Skip to content
Snippets Groups Projects
Commit 29a60fab authored by Felipe D'Abrantes's avatar Felipe D'Abrantes
Browse files

Add more commenting and type declaration

parent 27e7bb87
No related branches found
No related tags found
1 merge request!14Add endpoints to manage Dailies
...@@ -2,6 +2,7 @@ package controllers ...@@ -2,6 +2,7 @@ package controllers
import javax.inject._ import javax.inject._
import play.api.mvc._ import play.api.mvc._
import play.api.libs.json.JsValue
import models.{Daily} import models.{Daily}
...@@ -22,7 +23,7 @@ class DailyController @Inject()(val controllerComponents: ControllerComponents) ...@@ -22,7 +23,7 @@ class DailyController @Inject()(val controllerComponents: ControllerComponents)
try { try {
val result: Seq[Daily] = Daily.getAllDailiesAsync() val result: Seq[Daily] = Daily.getAllDailiesAsync()
val jsonResult = Daily.toJson(result) val jsonResult: JsValue = Daily.toJson(result)
Ok(jsonResult) Ok(jsonResult)
} catch { } catch {
case _: TimeoutException => BadRequest("Request timed out") case _: TimeoutException => BadRequest("Request timed out")
...@@ -38,7 +39,7 @@ class DailyController @Inject()(val controllerComponents: ControllerComponents) ...@@ -38,7 +39,7 @@ class DailyController @Inject()(val controllerComponents: ControllerComponents)
try { try {
val result: Seq[Daily] = Daily.getUserDailiesAsync(new ObjectId("641128f7e80bcd1ba39d04af")) val result: Seq[Daily] = Daily.getUserDailiesAsync(new ObjectId("641128f7e80bcd1ba39d04af"))
val jsonResult = Daily.toJson(result) val jsonResult: JsValue = Daily.toJson(result)
Ok(jsonResult) Ok(jsonResult)
} catch { } catch {
case _: TimeoutException => BadRequest("Request timed out") case _: TimeoutException => BadRequest("Request timed out")
...@@ -54,7 +55,7 @@ class DailyController @Inject()(val controllerComponents: ControllerComponents) ...@@ -54,7 +55,7 @@ class DailyController @Inject()(val controllerComponents: ControllerComponents)
try { try {
val result: Seq[Daily] = Daily.getUserFeedAsync(new ObjectId("641128f7e80bcd1ba39d04ae")) val result: Seq[Daily] = Daily.getUserFeedAsync(new ObjectId("641128f7e80bcd1ba39d04ae"))
val jsonResult = Daily.toJson(result) val jsonResult: JsValue = Daily.toJson(result)
Ok(jsonResult) Ok(jsonResult)
} catch { } catch {
case _: TimeoutException => BadRequest("Request timed out") case _: TimeoutException => BadRequest("Request timed out")
...@@ -62,13 +63,16 @@ class DailyController @Inject()(val controllerComponents: ControllerComponents) ...@@ -62,13 +63,16 @@ class DailyController @Inject()(val controllerComponents: ControllerComponents)
} }
} }
/**
* Create an Action to create a Daily.
*/
def create() = Action { def create() = Action {
println("DailyController:create") println("DailyController:create")
try { try {
// Dummy data // Dummy data
val result = Daily.createDailyAsync(new ObjectId("641128f7e80bcd1ba39d04ae"), new ObjectId("641128f7e80bcd1ba39d04ae"), "asddas") val result: Daily = Daily.createDailyAsync(new ObjectId("641128f7e80bcd1ba39d04ae"), new ObjectId("641128f7e80bcd1ba39d04ae"), "asddas")
val jsonResult = Daily.toJson(result) val jsonResult: JsValue = Daily.toJson(result)
Ok(jsonResult) Ok(jsonResult)
} catch { } catch {
case _: TimeoutException => BadRequest("Request timed out") case _: TimeoutException => BadRequest("Request timed out")
...@@ -76,6 +80,9 @@ class DailyController @Inject()(val controllerComponents: ControllerComponents) ...@@ -76,6 +80,9 @@ class DailyController @Inject()(val controllerComponents: ControllerComponents)
} }
} }
/**
* Create an Action to like a Daily.
*/
def like() = Action { def like() = Action {
println("DailyController:like") println("DailyController:like")
......
...@@ -36,17 +36,17 @@ object Daily { ...@@ -36,17 +36,17 @@ object Daily {
val now: Date = Date.from(Instant.now()) val now: Date = Date.from(Instant.now())
val daily: Daily = Daily(None, userId, questionId, content, Seq.empty[ObjectId], now, now) val daily: Daily = Daily(None, userId, questionId, content, Seq.empty[ObjectId], now, now)
val future: Future[Daily] = dailyRepo.insertDaily(daily) val future: Future[Daily] = dailyRepo.insertDaily(daily)
Await.result(future, timeout.seconds) Await.result[Daily](future, timeout.seconds)
} }
def getAllDailiesAsync(timeout: Int = 4): Seq[Daily] = { def getAllDailiesAsync(timeout: Int = 4): Seq[Daily] = {
val future: Future[Seq[Daily]] = dailyRepo.getAllDailies() val future: Future[Seq[Daily]] = dailyRepo.getAllDailies()
Await.result(future, timeout.seconds) Await.result[Seq[Daily]](future, timeout.seconds)
} }
def getUserDailiesAsync(userId: ObjectId, timeout: Int = 4): Seq[Daily] = { def getUserDailiesAsync(userId: ObjectId, timeout: Int = 4): Seq[Daily] = {
val future: Future[Seq[Daily]] = dailyRepo.getUserDailies(userId) val future: Future[Seq[Daily]] = dailyRepo.getUserDailies(userId)
Await.result(future, timeout.seconds) Await.result[Seq[Daily]](future, timeout.seconds)
} }
def getUserFeedAsync(userId: ObjectId, timeout: Int = 4): Seq[Daily] = { def getUserFeedAsync(userId: ObjectId, timeout: Int = 4): Seq[Daily] = {
...@@ -56,7 +56,7 @@ object Daily { ...@@ -56,7 +56,7 @@ object Daily {
feed: Seq[Daily] <- dailyRepo.getUserDailies(friends) feed: Seq[Daily] <- dailyRepo.getUserDailies(friends)
} yield feed } yield feed
Await.result(result, timeout.seconds) Await.result[Seq[Daily]](result, timeout.seconds)
} }
def likeAsync(dailyId: ObjectId, userId: ObjectId, timeout: Int = 4): Unit = { def likeAsync(dailyId: ObjectId, userId: ObjectId, timeout: Int = 4): Unit = {
...@@ -65,12 +65,12 @@ object Daily { ...@@ -65,12 +65,12 @@ object Daily {
unit: Unit <- dailyRepo.like(daily, userId) unit: Unit <- dailyRepo.like(daily, userId)
} yield unit } yield unit
Await.result(result, timeout.seconds) Await.result[Unit](result, timeout.seconds)
} }
// Convert from Daily object to JSON (serializing to JSON) // Convert from Daily object to JSON (serializing to JSON)
def toJson(daily: Daily): JsValue = { def toJson(daily: Daily): JsValue = {
val usersLikedAsJsStrings = daily.usersLiked.map(id => JsString(id.toString())) val usersLikedAsJsStrings: Seq[JsString] = daily.usersLiked.map[JsString](id => JsString(id.toString()))
val dateFormat: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") val dateFormat: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
val formattedCreatedAt: String = dateFormat.format(daily.createdAt) val formattedCreatedAt: String = dateFormat.format(daily.createdAt)
...@@ -86,14 +86,14 @@ object Daily { ...@@ -86,14 +86,14 @@ object Daily {
"updatedAt" -> JsString(formattedUpdatedAt) "updatedAt" -> JsString(formattedUpdatedAt)
) )
Json.toJson(JsObject(dailyJson)) Json.toJson[JsObject](JsObject(dailyJson))
} }
// Convert from Daily set to JSON (serializing to JSON) // Convert from Daily set to JSON (serializing to JSON)
def toJson(dailies: Seq[Daily]): JsValue = { def toJson(dailies: Seq[Daily]): JsValue = {
val dailiesJson = dailies.map(daily => Daily.toJson(daily)) val dailiesJson: Seq[JsValue] = dailies.map(daily => Daily.toJson(daily))
Json.toJson(JsArray(dailiesJson)) Json.toJson[JsArray](JsArray(dailiesJson))
} }
def toString(daily: Daily): String = def toString(daily: Daily): String =
......
...@@ -3,6 +3,7 @@ package models ...@@ -3,6 +3,7 @@ package models
import utils.ConfigHelper import utils.ConfigHelper
import org.mongodb.scala.{MongoClient, MongoDatabase, MongoCollection, Document} import org.mongodb.scala.{MongoClient, MongoDatabase, MongoCollection, Document}
import com.mongodb.client.result.{InsertOneResult, UpdateResult}
import org.mongodb.scala.model.{Filters, Projections, Sorts} import org.mongodb.scala.model.{Filters, Projections, Sorts}
import org.bson.conversions.Bson import org.bson.conversions.Bson
import org.bson.types.ObjectId import org.bson.types.ObjectId
...@@ -67,8 +68,8 @@ class MongoDBClient { ...@@ -67,8 +68,8 @@ class MongoDBClient {
projection: Bson = Projections.excludeId(), projection: Bson = Projections.excludeId(),
sort: Bson = Sorts.ascending("_id") sort: Bson = Sorts.ascending("_id")
): Future[Seq[Document]] = { ): Future[Seq[Document]] = {
collection.find(filter) collection.find[Document](filter)
.projection(projection) // .projection(projection)
.sort(sort) .sort(sort)
.toFuture() .toFuture()
} }
...@@ -82,9 +83,9 @@ class MongoDBClient { ...@@ -82,9 +83,9 @@ class MongoDBClient {
* @throws RuntimeException if the insertion was not acknowledged by the database. * @throws RuntimeException if the insertion was not acknowledged by the database.
*/ */
def insertOne(collection: MongoCollection[Document], document: Document): Future[String] = { def insertOne(collection: MongoCollection[Document], document: Document): Future[String] = {
val futureResult = collection.insertOne(document).toFuture() val futureResult: Future[InsertOneResult] = collection.insertOne(document).toFuture()
futureResult.map(result => { futureResult.map[String]((result: InsertOneResult) => {
if (result.wasAcknowledged()) { if (result.wasAcknowledged()) {
// Grab the generated ID of the inserted document // Grab the generated ID of the inserted document
result.getInsertedId().asObjectId.getValue().toString() result.getInsertedId().asObjectId.getValue().toString()
...@@ -103,10 +104,10 @@ class MongoDBClient { ...@@ -103,10 +104,10 @@ class MongoDBClient {
* @throws RuntimeException if the update was not acknowledged by the database. * @throws RuntimeException if the update was not acknowledged by the database.
*/ */
def updateOne(collection: MongoCollection[Document], documentId: ObjectId, updates: Seq[Bson]): Future[Unit] = { def updateOne(collection: MongoCollection[Document], documentId: ObjectId, updates: Seq[Bson]): Future[Unit] = {
val filter = Filters.equal("_id", documentId) val filter: Bson = Filters.equal[ObjectId]("_id", documentId)
val futureResult = collection.updateOne(filter, updates).toFuture() val futureResult: Future[UpdateResult] = collection.updateOne(filter, updates).toFuture()
futureResult.map(result => { futureResult.map[Unit]((result: UpdateResult) => {
if (!result.wasAcknowledged()) { if (!result.wasAcknowledged()) {
throw new RuntimeException("Update was not acknowledged") throw new RuntimeException("Update was not acknowledged")
} }
......
package repositories package repositories
import com.typesafe.config.ConfigFactory import com.typesafe.config.{Config, ConfigFactory}
import models.{Daily, MongoDBClient} import models.{Daily, MongoDBClient}
import org.mongodb.scala.{MongoCollection, Document} import org.mongodb.scala.{MongoDatabase, MongoCollection, Document}
import org.mongodb.scala.model.{Filters, Updates} import org.mongodb.scala.model.{Filters, Updates}
import org.bson.types.ObjectId import org.bson.types.ObjectId
import org.bson.conversions.Bson import org.bson.conversions.Bson
...@@ -18,10 +18,10 @@ import scala.collection.JavaConverters._ ...@@ -18,10 +18,10 @@ import scala.collection.JavaConverters._
class DailyRepository extends MongoDBClient { class DailyRepository extends MongoDBClient {
// Loads the default configuration // Loads the default configuration
private val config = ConfigFactory.load() private val config: Config = ConfigFactory.load()
private val databaseName = config.getString("mongo.feedService.db") private val databaseName: String = config.getString("mongo.feedService.db")
private val collectionName = config.getString("mongo.dailies.collection") private val collectionName: String = config.getString("mongo.dailies.collection")
/** /**
* Returns a reference to a MongoDB collection within a database. * Returns a reference to a MongoDB collection within a database.
...@@ -31,12 +31,12 @@ class DailyRepository extends MongoDBClient { ...@@ -31,12 +31,12 @@ class DailyRepository extends MongoDBClient {
* @throws TimeoutException if the Future doesn't complete within the 3 second timeout. * @throws TimeoutException if the Future doesn't complete within the 3 second timeout.
*/ */
private def dailiesCollection: MongoCollection[Document] = { private def dailiesCollection: MongoCollection[Document] = {
val futureCollection = for { val futureCollection: Future[MongoCollection[Document]] = for {
database <- getDatabase(databaseName) database: MongoDatabase <- getDatabase(databaseName)
collection <- getCollection(database, collectionName) collection: MongoCollection[Document] <- getCollection(database, collectionName)
} yield collection } yield collection
Await.result(futureCollection, 3.seconds) Await.result[MongoCollection[Document]](futureCollection, 3.seconds)
} }
/** /**
...@@ -47,7 +47,7 @@ class DailyRepository extends MongoDBClient { ...@@ -47,7 +47,7 @@ class DailyRepository extends MongoDBClient {
def getDaily(dailyId: ObjectId): Future[Daily] = { def getDaily(dailyId: ObjectId): Future[Daily] = {
val filter = Filters.equal("_id", dailyId) val filter = Filters.equal("_id", dailyId)
val document: Future[Document] = find(dailiesCollection, filter).map(x => x(0)) val document: Future[Document] = find(dailiesCollection, filter).map(x => x(0))
document.map(doc => DailyRepository.fromMongoDocument(doc)) document.map[Daily](doc => DailyRepository.fromMongoDocument(doc))
} }
/** /**
...@@ -57,7 +57,7 @@ class DailyRepository extends MongoDBClient { ...@@ -57,7 +57,7 @@ class DailyRepository extends MongoDBClient {
*/ */
def getAllDailies(): Future[Seq[Daily]] = { def getAllDailies(): Future[Seq[Daily]] = {
val documents: Future[Seq[Document]] = find(dailiesCollection) val documents: Future[Seq[Document]] = find(dailiesCollection)
documents.map(docs => DailyRepository.fromMongoDocument(docs)) documents.map[Seq[Daily]](docs => DailyRepository.fromMongoDocument(docs))
} }
/** /**
...@@ -66,10 +66,10 @@ class DailyRepository extends MongoDBClient { ...@@ -66,10 +66,10 @@ class DailyRepository extends MongoDBClient {
* @return A Future containing a sequence of the user's Daily objects. * @return A Future containing a sequence of the user's Daily objects.
*/ */
def getUserDailies(userId: ObjectId): Future[Seq[Daily]] = { def getUserDailies(userId: ObjectId): Future[Seq[Daily]] = {
val userFilter = Filters.equal("user_id", userId) val userFilter: Bson = Filters.equal("user_id", userId)
val documents: Future[Seq[Document]] = find(dailiesCollection, userFilter) val documents: Future[Seq[Document]] = find(dailiesCollection, userFilter)
documents.map(docs => DailyRepository.fromMongoDocument(docs)) documents.map[Seq[Daily]](docs => DailyRepository.fromMongoDocument(docs))
} }
/** /**
...@@ -79,10 +79,10 @@ class DailyRepository extends MongoDBClient { ...@@ -79,10 +79,10 @@ class DailyRepository extends MongoDBClient {
*/ */
def getUserDailies(userIds: Seq[ObjectId]): Future[Seq[Daily]] = { def getUserDailies(userIds: Seq[ObjectId]): Future[Seq[Daily]] = {
// The syntax userIds: _* is used to convert the List of ObjectId instances to a variable-length argument list // The syntax userIds: _* is used to convert the List of ObjectId instances to a variable-length argument list
val userFilter = Filters.in("user_id", userIds: _*) val userFilter: Bson = Filters.in("user_id", userIds: _*)
val documents: Future[Seq[Document]] = find(dailiesCollection, userFilter) val documents: Future[Seq[Document]] = find(dailiesCollection, userFilter)
documents.map(docs => DailyRepository.fromMongoDocument(docs)) documents.map[Seq[Daily]](docs => DailyRepository.fromMongoDocument(docs))
} }
/** /**
...@@ -92,7 +92,7 @@ class DailyRepository extends MongoDBClient { ...@@ -92,7 +92,7 @@ class DailyRepository extends MongoDBClient {
*/ */
def insertDaily(daily: Daily): Future[Daily] = { def insertDaily(daily: Daily): Future[Daily] = {
// Don't supply an ID as Mongo will generate one for us // Don't supply an ID as Mongo will generate one for us
val document = Document( val document: Document = Document(
"user_id" -> daily.userId, "user_id" -> daily.userId,
"question_id" -> daily.questionId, "question_id" -> daily.questionId,
"content" -> daily.content, "content" -> daily.content,
...@@ -101,21 +101,24 @@ class DailyRepository extends MongoDBClient { ...@@ -101,21 +101,24 @@ class DailyRepository extends MongoDBClient {
"updatedAt" -> daily.updatedAt "updatedAt" -> daily.updatedAt
) )
val result = insertOne(dailiesCollection, document) val result: Future[String] = insertOne(dailiesCollection, document)
// Return a Daily entity with the generated ID // Return a Daily entity with the generated ID
result.flatMap(id => { result.flatMap[Daily](id => {
val updatedDaily = daily.copy(id = Some(new ObjectId(id))) val updatedDaily: Daily = daily.copy(id = Some(new ObjectId(id)))
Future.successful(updatedDaily) Future.successful(updatedDaily)
}) })
} }
/**
* Add a user like to the given Daily record in the database.
*/
def like(daily: Daily, user: ObjectId): Future[Unit] = { def like(daily: Daily, user: ObjectId): Future[Unit] = {
val updatedUsersLiked: Seq[ObjectId] = daily.usersLiked :+ user val updatedUsersLiked: Seq[ObjectId] = daily.usersLiked :+ user
val update: Bson = Updates.set("usersLiked", updatedUsersLiked) val update: Bson = Updates.set("usersLiked", updatedUsersLiked)
val updates: Seq[Bson] = Seq(update) val updates: Seq[Bson] = Seq(update)
val dailyId = daily.id.getOrElse(throw new RuntimeException) val dailyId: ObjectId = daily.id.getOrElse(throw new RuntimeException)
updateOne(dailiesCollection, dailyId, updates) updateOne(dailiesCollection, dailyId, updates)
} }
} }
...@@ -135,6 +138,6 @@ object DailyRepository { ...@@ -135,6 +138,6 @@ object DailyRepository {
} }
def fromMongoDocument(documents: Seq[Document]): Seq[Daily] = { def fromMongoDocument(documents: Seq[Document]): Seq[Daily] = {
documents.map(document => DailyRepository.fromMongoDocument(document)) documents.map[Daily](document => DailyRepository.fromMongoDocument(document))
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment