MongoDBService.scala 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package com.weEat.services
  2. import play.api.Configuration
  3. import org.mongodb.scala.{MongoClient,MongoDatabase,MongoCollection}
  4. import org.mongodb.scala.bson.codecs.Macros._
  5. import org.bson.{BsonReader,BsonWriter}
  6. import org.bson.codecs.{Codec,DecoderContext,EncoderContext}
  7. import org.bson.codecs.configuration.{CodecProvider,CodecRegistry}
  8. import org.bson.codecs.configuration.CodecRegistries.{fromRegistries,fromProviders}
  9. import com.weEat.models._
  10. import com.weEat.shared.models.{USDANode,RecipeNode,FoodNode,UnitType}
  11. import javax.inject.{Inject,Singleton}
  12. import scala.reflect.ClassTag
  13. import com.weEat.migrations.{Migration,Metadata}
  14. import scala.concurrent.ExecutionContext
  15. import scala.util.{Try,Success,Failure}
  16. import gov.usda.nal.fdc.models.Nutrient
  17. @Singleton
  18. class MongoDBService @Inject()(config: Configuration) {
  19. implicit val ec = scala.concurrent.ExecutionContext.global
  20. private val prefix = "mongo"
  21. val url = config.getOptional[String](s"$prefix.url").getOrElse("localhost")
  22. val name = config.getOptional[String](s"$prefix.name").getOrElse("recipes")
  23. val user = config.getOptional[String](s"$prefix.user").getOrElse("application")
  24. val ssl = config.getOptional[Boolean](s"$prefix.ssl").getOrElse(true)
  25. val port = config.getOptional[Int](s"$prefix.port").getOrElse(27017)
  26. val codecRegistry = fromRegistries(
  27. fromProviders(classOf[Metadata]),
  28. fromProviders(classOf[FoodNode]),
  29. fromProviders(classOf[User]),
  30. fromProviders(classOf[Authorization]),
  31. fromProviders(classOf[Nutrient]),
  32. //fromProviders(classOf[UnitType.Value]),
  33. fromProviders(UnitTypeEnumCodecProvider),
  34. MongoClient.DEFAULT_CODEC_REGISTRY
  35. )
  36. val con = {
  37. import org.mongodb.scala._
  38. import org.mongodb.scala.connection.{SslSettings,ClusterSettings}
  39. import scala.jdk.CollectionConverters._
  40. implicit val ec: ExecutionContext = ExecutionContext.global
  41. val password = Option(config.get[String](s"$prefix.password"))
  42. .getOrElse("").toCharArray()
  43. val credential = MongoCredential.createCredential(user, name, password)
  44. val db = MongoClient(
  45. MongoClientSettings.builder()
  46. .applyToSslSettings((builder: SslSettings.Builder) =>
  47. builder.enabled(ssl)
  48. ).applyToClusterSettings((builder: ClusterSettings.Builder) =>
  49. builder.hosts(List(new ServerAddress(url, port)).asJava)
  50. ).credential(credential)
  51. .build()
  52. ).getDatabase(name)
  53. .withCodecRegistry(codecRegistry)
  54. Migration.updateToLatest(db).map(_ => db)
  55. }
  56. def apply[T](coll: Collectable[T])(implicit ct: ClassTag[T]) =
  57. con.map(_.getCollection[T](coll.collectionName))
  58. def withCollection[T, U](coll: Collectable[U])(fn: (MongoCollection[U] => T))
  59. (implicit ct: ClassTag[U]) =
  60. apply(coll).transform({
  61. case Success(collection) => Success(fn(collection))
  62. case Failure(e) => Failure(e)
  63. })
  64. }
  65. object UnitTypeEnumCodecProvider extends CodecProvider {
  66. def isCaseObjectEnum[T](clazz: Class[T]): Boolean =
  67. clazz.isInstance(UnitType.MASS) ||
  68. clazz.isInstance(UnitType.VOLUME) ||
  69. clazz.isInstance(UnitType.NUMBER)
  70. override def get[T](clazz: Class[T], registry: CodecRegistry): Codec[T] =
  71. if (isCaseObjectEnum(clazz)) UnitTypeEnumCodec.asInstanceOf[Codec[T]]
  72. else null
  73. object UnitTypeEnumCodec extends Codec[UnitType.UnitType] {
  74. override def decode(
  75. reader: BsonReader,
  76. decoderContext: DecoderContext
  77. ): UnitType.UnitType = UnitType.withName(reader.readString())
  78. override def encode(
  79. writer: BsonWriter,
  80. value: UnitType.UnitType,
  81. encoderContext: EncoderContext
  82. ): Unit = writer.writeString(value.name)
  83. override def getEncoderClass: Class[UnitType.UnitType] =
  84. UnitType.getClass.asInstanceOf[Class[UnitType.UnitType]]
  85. }
  86. }