Skip to content

Commit b1f5d78

Browse files
committed
feat: use circe scheme to convert documents to objects
1 parent 968c4b5 commit b1f5d78

21 files changed

Lines changed: 143 additions & 98 deletions

src/main/scala/dev/mongocamp/driver/mongodb/MongoDAO.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import java.nio.charset.Charset
1818
import java.util.Date
1919
import scala.collection.mutable.ArrayBuffer
2020
import scala.reflect.ClassTag
21-
21+
import dev.mongocamp.driver.mongodb.schema.JsonConverter._
2222
/** Created by tom on 20.01.17.
2323
*/
2424
abstract class MongoDAO[A](provider: DatabaseProvider, collectionName: String)(implicit ct: ClassTag[A], decoder: Decoder[A]) extends Crud[A] {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package dev.mongocamp.driver.mongodb.bson
2+
3+
import org.bson.BsonValue
4+
import org.mongodb.scala.bson.BsonNull
5+
6+
abstract class AbstractConverterPlugin {
7+
8+
def customClassList: List[Class[_]] = {
9+
List()
10+
}
11+
12+
def hasCustomClass(v: Any): Boolean = {
13+
customClassList.exists(c => c.isAssignableFrom(v.getClass))
14+
}
15+
16+
def objectToBson(value: AnyRef): BsonValue = {
17+
val map: Map[String, Any] = ClassUtil.membersToMap(value)
18+
BsonConverter.toBson(map)
19+
}
20+
21+
def toBson(value: Any): BsonValue =
22+
value match {
23+
case _ =>
24+
BsonNull()
25+
}
26+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package dev.mongocamp.driver.mongodb.bson
2+
3+
class BaseConverterPlugin extends AbstractConverterPlugin

src/main/scala/dev/mongocamp/driver/mongodb/bson/ConverterPlugin.scala renamed to src/main/scala/dev/mongocamp/driver/mongodb/bson/ClassUtil.scala

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,8 @@
11
package dev.mongocamp.driver.mongodb.bson
22

33
import java.lang.reflect.Field
4-
5-
import org.bson.BsonValue
6-
import org.mongodb.scala.bson.BsonNull
7-
84
import scala.collection.mutable
95

10-
class BaseConverterPlugin extends AbstractConverterPlugin
11-
12-
abstract class AbstractConverterPlugin {
13-
14-
def customClassList: List[Class[_]] = List()
15-
16-
def hasCustomClass(v: Any): Boolean =
17-
customClassList.exists(c => c.isAssignableFrom(v.getClass))
18-
19-
def objectToBson(value: AnyRef): BsonValue = {
20-
val map: Map[String, Any] = ClassUtil.membersToMap(value)
21-
BsonConverter.toBson(map)
22-
}
23-
24-
def toBson(value: Any): BsonValue =
25-
value match {
26-
case _ =>
27-
BsonNull()
28-
}
29-
}
30-
316
object ClassUtil {
327
private val classRegistry =
338
new mutable.HashMap[Class[_], Map[String, Field]]()

src/main/scala/dev/mongocamp/driver/mongodb/database/ChangeObserver.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ case class ChangeObserver[A](onChangeCallback: ChangeStreamDocument[A] => Unit)
88

99
override def onSubscribe(subscription: Subscription): Unit = subscription.request(Long.MaxValue) // Request data
1010

11-
override def onNext(changeDocument: ChangeStreamDocument[A]): Unit =
11+
override def onNext(changeDocument: ChangeStreamDocument[A]): Unit = {
1212
onChangeCallback(changeDocument)
13+
}
1314

14-
override def onError(throwable: Throwable): Unit =
15+
override def onError(throwable: Throwable): Unit = {
1516
logger.error(throwable.getMessage, throwable)
17+
}
1618

1719
override def onComplete(): Unit = {}
1820

src/main/scala/dev/mongocamp/driver/mongodb/database/DatabaseProvider.scala

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package dev.mongocamp.driver.mongodb.database
22

33
import dev.mongocamp.driver.mongodb._
4-
import dev.mongocamp.driver.mongodb.bson.codecs.CustomCodecProvider
5-
import org.bson.codecs.configuration.CodecRegistries.{ fromProviders, fromRegistries }
6-
import org.bson.codecs.configuration.CodecRegistry
7-
import org.mongodb.scala.MongoClient.DEFAULT_CODEC_REGISTRY
4+
import dev.mongocamp.driver.mongodb.schema.JsonConverter._
85
import org.mongodb.scala._
96
import org.mongodb.scala.gridfs.GridFSBucket
107

src/main/scala/dev/mongocamp/driver/mongodb/gridfs/Metadata.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import org.mongodb.scala.model.Filters.equal
1010
import org.mongodb.scala.model.Updates._
1111
import org.mongodb.scala.result.UpdateResult
1212
import org.mongodb.scala.{ Document, Observable }
13+
import dev.mongocamp.driver.mongodb.schema.JsonConverter._
1314

1415
abstract class Metadata(provider: DatabaseProvider, bucketName: String) extends Crud {
1516

src/main/scala/dev/mongocamp/driver/mongodb/operation/Base.scala

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,32 @@ package dev.mongocamp.driver.mongodb.operation
33
import com.typesafe.scalalogging.LazyLogging
44
import dev.mongocamp.driver.mongodb.bson.BsonConverter
55
import dev.mongocamp.driver.mongodb.database.MongoIndex
6-
import dev.mongocamp.driver.mongodb.schema.{ CirceSchema, JsonConverter }
6+
import dev.mongocamp.driver.mongodb.schema.CirceSchema
7+
import io.circe.Decoder
8+
import io.circe.jawn.decode
9+
import io.circe.syntax._
710
import org.mongodb.scala.bson.conversions.Bson
811
import org.mongodb.scala.model.Sorts._
912
import org.mongodb.scala.model.{ CountOptions, DropIndexOptions, IndexOptions, Indexes }
1013
import org.mongodb.scala.{ Document, ListIndexesObservable, MongoCollection, Observable, SingleObservable }
1114

1215
import scala.collection.mutable
13-
import scala.concurrent.duration.Duration
14-
import scala.concurrent.duration.durationToPair
16+
import scala.concurrent.duration.{ durationToPair, Duration }
1517
import scala.reflect.ClassTag
16-
import io.circe.generic.auto._
17-
import io.circe.syntax._
18-
import better.files.Resource
19-
import io.circe.{ Decoder, HCursor }
20-
import io.circe.jawn.decode
21-
import io.circe.syntax._
22-
import io.circe.generic.auto._
2318

24-
abstract class Base[A](implicit classTag: ClassTag[A]) extends LazyLogging {
25-
def jsonConverter = new JsonConverter()
26-
def documentToObject[A](document: Document)(implicit decoder: Decoder[A]): A = {
19+
abstract class Base[A](implicit classTag: ClassTag[A]) extends LazyLogging with CirceSchema {
20+
def documentToObject[A](document: Document, decoder: Decoder[A]): A = {
2721
if (classTag.runtimeClass == classOf[Document]) {
2822
document.asInstanceOf[A]
2923
}
3024
else {
31-
val helperMap = mutable.Map[String, Any]()
32-
document.keys.foreach(k => helperMap.put(k, BsonConverter.fromBson(document(k))))
33-
val jsonString = jsonConverter.toJson(helperMap)
34-
val response = jsonConverter.toObject(jsonString)
35-
// val decoder = converter.decodeString[A](jsonString)
36-
response
25+
val helperMap = BsonConverter.asMap(document)
26+
val jsonString = helperMap.asJson.noSpaces
27+
val response = decode[A](jsonString)(decoder)
28+
if (response.isLeft) {
29+
logger.error(s"Error decoding document to object: ${response.swap.getOrElse("")}")
30+
}
31+
response.getOrElse(null.asInstanceOf[A])
3732
}
3833
}
3934

src/main/scala/dev/mongocamp/driver/mongodb/operation/Crud.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package dev.mongocamp.driver.mongodb.operation
33
import dev.mongocamp.driver.mongodb.database.DatabaseProvider
44
import dev.mongocamp.driver.mongodb.sync.MongoSyncOperation
55
import dev.mongocamp.driver.mongodb.{ Converter, _ }
6+
import io.circe.Decoder
67
import org.mongodb.scala.bson.conversions.Bson
78
import org.mongodb.scala.model.Filters._
89
import org.mongodb.scala.model.Updates._
@@ -14,7 +15,7 @@ import java.util.Date
1415
import scala.collection.mutable.ArrayBuffer
1516
import scala.reflect.ClassTag
1617

17-
abstract class Crud[A]()(implicit ct: ClassTag[A]) extends Search[A] {
18+
abstract class Crud[A]()(implicit ct: ClassTag[A], decoder: Decoder[A]) extends Search[A] {
1819

1920
// create
2021
def insertOne(value: A): Observable[InsertOneResult] = {

src/main/scala/dev/mongocamp/driver/mongodb/operation/Search.scala

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
package dev.mongocamp.driver.mongodb.operation
22

33
import dev.mongocamp.driver.mongodb._
4-
import dev.mongocamp.driver.mongodb.bson.BsonConverter
54
import dev.mongocamp.driver.mongodb.bson.BsonConverter._
65
import dev.mongocamp.driver.mongodb.database.DatabaseProvider
7-
import io.circe.Decoder.Result
8-
import io.circe.{ Decoder, HCursor }
6+
import io.circe.Decoder
97
import org.bson.BsonValue
108
import org.mongodb.scala.bson.ObjectId
119
import org.mongodb.scala.bson.conversions.Bson
1210
import org.mongodb.scala.model.Filters._
13-
import org.mongodb.scala.{ AggregateObservable, DistinctObservable, Document, FindObservable, MongoCollection, Observable }
11+
import org.mongodb.scala.{ DistinctObservable, Document, MongoCollection, Observable }
1412

1513
import scala.reflect.ClassTag
1614

17-
abstract class Search[A]()(implicit ct: ClassTag[A]) extends Base[A] {
15+
abstract class Search[A]()(implicit ct: ClassTag[A], decoder: Decoder[A]) extends Base[A] {
1816

1917
protected def coll: MongoCollection[Document]
2018

@@ -23,7 +21,7 @@ abstract class Search[A]()(implicit ct: ClassTag[A]) extends Base[A] {
2321
sort: Bson = Document(),
2422
projection: Bson = Document(),
2523
limit: Int = 0
26-
)(implicit decoder: Decoder[A]): Observable[A] = {
24+
): Observable[A] = {
2725
val findObservable = {
2826
if (limit > 0) {
2927
coll.find(filter).sort(sort).projection(projection).limit(limit)
@@ -32,14 +30,14 @@ abstract class Search[A]()(implicit ct: ClassTag[A]) extends Base[A] {
3230
coll.find(filter).sort(sort).projection(projection)
3331
}
3432
}
35-
findObservable.map(doc => documentToObject[A](doc))
33+
findObservable.map(doc => documentToObject[A](doc, decoder))
3634
}
3735

38-
def findById(oid: ObjectId)(implicit decoder: Decoder[A]): Observable[A] = {
36+
def findById(oid: ObjectId): Observable[A] = {
3937
find(equal(DatabaseProvider.ObjectIdKey, oid))
4038
}
4139

42-
def find(name: String, value: Any)(implicit decoder: Decoder[A]): Observable[A] = {
40+
def find(name: String, value: Any): Observable[A] = {
4341
find(equal(name, value))
4442
}
4543

@@ -51,13 +49,13 @@ abstract class Search[A]()(implicit ct: ClassTag[A]) extends Base[A] {
5149
distinct(fieldName, filter).resultList().map(v => fromBson(v).asInstanceOf[S])
5250
}
5351

54-
def findAggregated(pipeline: Seq[Bson], allowDiskUse: Boolean = false)(implicit decoder: Decoder[A]): Observable[A] = {
52+
def findAggregated(pipeline: Seq[Bson], allowDiskUse: Boolean = false): Observable[A] = {
5553
val aggregateObservable = coll.aggregate(pipeline).allowDiskUse(allowDiskUse)
5654
aggregateObservable.map {
5755
case a: A =>
5856
a
5957
case doc =>
60-
documentToObject[A](doc)
58+
documentToObject[A](doc, decoder)
6159
}
6260
}
6361

0 commit comments

Comments
 (0)