Skip to content

Commit 968c4b5

Browse files
committed
feat: try to implement conversion from document to object with circe
1 parent 91ed0be commit 968c4b5

14 files changed

Lines changed: 122 additions & 49 deletions

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ import better.files.File
44
import dev.mongocamp.driver.mongodb.bson.{ BsonConverter, DocumentHelper }
55
import dev.mongocamp.driver.mongodb.database.{ ChangeObserver, CollectionStatus, CompactResult, DatabaseProvider }
66
import dev.mongocamp.driver.mongodb.operation.Crud
7+
import io.circe.Decoder
78
import org.bson.json.JsonParseException
89
import org.mongodb.scala.model.Accumulators._
910
import org.mongodb.scala.model.Aggregates._
1011
import org.mongodb.scala.model.Filters._
1112
import org.mongodb.scala.model.Projections
1213
import org.mongodb.scala.{ BulkWriteResult, Document, MongoCollection, Observable, SingleObservable }
14+
import dev.mongocamp.driver.mongodb.schema.JsonConverter._
15+
import io.circe.generic.auto._
1316

1417
import java.nio.charset.Charset
1518
import java.util.Date
@@ -18,7 +21,7 @@ import scala.reflect.ClassTag
1821

1922
/** Created by tom on 20.01.17.
2023
*/
21-
abstract class MongoDAO[A](provider: DatabaseProvider, collectionName: String)(implicit ct: ClassTag[A]) extends Crud[A] {
24+
abstract class MongoDAO[A](provider: DatabaseProvider, collectionName: String)(implicit ct: ClassTag[A], decoder: Decoder[A]) extends Crud[A] {
2225

2326
val databaseName: String = provider.guessDatabaseName(collectionName)
2427

src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSet.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import java.nio.charset.StandardCharsets
1717
import javax.sql.rowset.serial.SerialBlob
1818
import scala.util.Try
1919
import org.mongodb.scala.documentToUntypedDocument
20+
import dev.mongocamp.driver.mongodb.schema.JsonConverter._
2021

2122
class MongoDbResultSet(collectionDao: MongoDAO[Document], data: List[Document], queryTimeOut: Int) extends ResultSet with MongoJdbcCloseable {
2223
private var currentRow: Document = _

src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSetMetaData.scala

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

3-
import dev.mongocamp.driver.mongodb.MongoDAO
3+
import dev.mongocamp.driver.mongodb.{ MongoDAO, _ }
4+
import dev.mongocamp.driver.mongodb.schema.JsonConverter._
45
import org.mongodb.scala.Document
56
import org.mongodb.scala.bson.{ BsonBoolean, BsonInt32, BsonInt64, BsonNumber, BsonString }
6-
import dev.mongocamp.driver.mongodb._
77

88
import java.sql.{ ResultSetMetaData, SQLException }
99

@@ -81,7 +81,7 @@ class MongoDbResultSetMetaData extends ResultSetMetaData {
8181
case _: BsonString => java.sql.Types.VARCHAR
8282
case _: BsonBoolean => java.sql.Types.BOOLEAN
8383
// case _: Document => java.sql.Types.STRUCT // todo: check if this is correct
84-
case _ => java.sql.Types.NULL
84+
case _ => java.sql.Types.NULL
8585
}
8686
}
8787

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

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,40 @@
11
package dev.mongocamp.driver.mongodb.operation
22

33
import com.typesafe.scalalogging.LazyLogging
4+
import dev.mongocamp.driver.mongodb.bson.BsonConverter
45
import dev.mongocamp.driver.mongodb.database.MongoIndex
6+
import dev.mongocamp.driver.mongodb.schema.{ CirceSchema, JsonConverter }
57
import org.mongodb.scala.bson.conversions.Bson
68
import org.mongodb.scala.model.Sorts._
79
import org.mongodb.scala.model.{ CountOptions, DropIndexOptions, IndexOptions, Indexes }
810
import org.mongodb.scala.{ Document, ListIndexesObservable, MongoCollection, Observable, SingleObservable }
911

12+
import scala.collection.mutable
1013
import scala.concurrent.duration.Duration
1114
import scala.concurrent.duration.durationToPair
12-
13-
abstract class Base[A] extends LazyLogging {
14-
15-
implicit def documentToObject[A](document: Document): A = {
16-
// docment to json
17-
// json to object
18-
null.asInstanceOf[A]
15+
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._
23+
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 = {
27+
if (classTag.runtimeClass == classOf[Document]) {
28+
document.asInstanceOf[A]
29+
}
30+
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
37+
}
1938
}
2039

2140
protected def coll: MongoCollection[Document]

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

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,57 @@
11
package dev.mongocamp.driver.mongodb.operation
22

3-
import java.util.Date
43
import dev.mongocamp.driver.mongodb.database.DatabaseProvider
4+
import dev.mongocamp.driver.mongodb.sync.MongoSyncOperation
55
import dev.mongocamp.driver.mongodb.{ Converter, _ }
66
import org.mongodb.scala.bson.conversions.Bson
77
import org.mongodb.scala.model.Filters._
8-
import org.mongodb.scala.model.{ BulkWriteOptions, _ }
8+
import org.mongodb.scala.model.Updates._
9+
import org.mongodb.scala.model._
910
import org.mongodb.scala.result.{ DeleteResult, InsertManyResult, InsertOneResult, UpdateResult }
10-
import org.mongodb.scala.{ BulkWriteResult, Observable, SingleObservable }
11+
import org.mongodb.scala.{ BulkWriteResult, Document, Observable, SingleObservable }
1112

13+
import java.util.Date
1214
import scala.collection.mutable.ArrayBuffer
1315
import scala.reflect.ClassTag
14-
import Updates._
15-
import dev.mongocamp.driver.mongodb.bson.BsonConverter
16-
import dev.mongocamp.driver.mongodb.sync.MongoSyncOperation
1716

1817
abstract class Crud[A]()(implicit ct: ClassTag[A]) extends Search[A] {
1918

2019
// create
21-
def insertOne(value: A): Observable[InsertOneResult] = coll.insertOne(Converter.toDocument(value))
20+
def insertOne(value: A): Observable[InsertOneResult] = {
21+
coll.insertOne(Converter.toDocument(value))
22+
}
2223

23-
def insertOne(value: A, options: InsertOneOptions): Observable[InsertOneResult] =
24+
def insertOne(value: A, options: InsertOneOptions): Observable[InsertOneResult] = {
2425
coll.insertOne(Converter.toDocument(value), options)
26+
}
2527

26-
def insertMany(values: Seq[A]): Observable[InsertManyResult] =
28+
def insertMany(values: Seq[A]): Observable[InsertManyResult] = {
2729
coll.insertMany(values.map(Converter.toDocument))
30+
}
2831

29-
def insertMany(values: Seq[A], options: InsertManyOptions): Observable[InsertManyResult] =
32+
def insertMany(values: Seq[A], options: InsertManyOptions): Observable[InsertManyResult] = {
3033
coll.insertMany(values.map(Converter.toDocument), options)
34+
}
3135

3236
// bulk write
3337

34-
def bulkWrite(requests: List[WriteModel[_ <: A]], options: BulkWriteOptions): SingleObservable[BulkWriteResult] = {
35-
// coll.bulkWrite(requests, options)
36-
// todo
37-
???
38+
def bulkWrite(requests: List[WriteModel[Document]], options: BulkWriteOptions): SingleObservable[BulkWriteResult] = {
39+
coll.bulkWrite(requests.map(wM => wM), options)
3840
}
3941

40-
def bulkWrite(requests: List[WriteModel[_ <: A]], ordered: Boolean = true): SingleObservable[BulkWriteResult] = {
42+
def bulkWrite(requests: List[WriteModel[Document]], ordered: Boolean = true): SingleObservable[BulkWriteResult] = {
4143
bulkWrite(requests, BulkWriteOptions().ordered(ordered))
4244
}
4345

4446
def bulkWriteMany(values: Seq[A], options: BulkWriteOptions): SingleObservable[BulkWriteResult] = {
45-
val requests: ArrayBuffer[WriteModel[_ <: A]] = ArrayBuffer()
46-
values.foreach(value => requests.append(InsertOneModel(value)))
47+
val requests: ArrayBuffer[WriteModel[Document]] = ArrayBuffer()
48+
values.foreach(value => requests.append(InsertOneModel(Converter.toDocument(value))))
4749
bulkWrite(requests.toList, options)
4850
}
4951

5052
def bulkWriteMany(values: Seq[A], ordered: Boolean = true): SingleObservable[BulkWriteResult] = {
51-
val requests: ArrayBuffer[WriteModel[_ <: A]] = ArrayBuffer()
52-
values.foreach(value => requests.append(InsertOneModel(value)))
53+
val requests: ArrayBuffer[WriteModel[Document]] = ArrayBuffer()
54+
values.foreach(value => requests.append(InsertOneModel(Converter.toDocument(value))))
5355
bulkWrite(requests.toList, ordered)
5456
}
5557

@@ -97,25 +99,33 @@ abstract class Crud[A]()(implicit ct: ClassTag[A]) extends Search[A] {
9799

98100
// delete
99101

100-
def deleteOne(filter: Bson): Observable[DeleteResult] = coll.deleteOne(filter)
102+
def deleteOne(filter: Bson): Observable[DeleteResult] = {
103+
coll.deleteOne(filter)
104+
}
101105

102-
def deleteOne(filter: Bson, options: DeleteOptions): Observable[DeleteResult] =
106+
def deleteOne(filter: Bson, options: DeleteOptions): Observable[DeleteResult] = {
103107
coll.deleteOne(filter, options)
108+
}
104109

105110
def deleteOne(value: A): Observable[DeleteResult] = {
106111
val oid = Converter.toDocument(value).get(DatabaseProvider.ObjectIdKey).get
107112
coll.deleteOne(equal(DatabaseProvider.ObjectIdKey, oid))
108113
}
109114

110-
def deleteMany(filter: Bson): Observable[DeleteResult] =
115+
def deleteMany(filter: Bson): Observable[DeleteResult] = {
111116
coll.deleteMany(filter)
117+
}
112118

113-
def deleteMany(filter: Bson, options: DeleteOptions): Observable[DeleteResult] =
119+
def deleteMany(filter: Bson, options: DeleteOptions): Observable[DeleteResult] = {
114120
coll.deleteMany(filter, options)
121+
}
115122

116-
def deleteAll(): Observable[DeleteResult] = deleteMany(Map())
123+
def deleteAll(): Observable[DeleteResult] = {
124+
deleteMany(Map())
125+
}
117126

118-
def deleteAll(options: DeleteOptions): Observable[DeleteResult] =
127+
def deleteAll(options: DeleteOptions): Observable[DeleteResult] = {
119128
deleteMany(Map(), options)
129+
}
120130

121131
}

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

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import dev.mongocamp.driver.mongodb._
44
import dev.mongocamp.driver.mongodb.bson.BsonConverter
55
import dev.mongocamp.driver.mongodb.bson.BsonConverter._
66
import dev.mongocamp.driver.mongodb.database.DatabaseProvider
7+
import io.circe.Decoder.Result
8+
import io.circe.{ Decoder, HCursor }
79
import org.bson.BsonValue
810
import org.mongodb.scala.bson.ObjectId
911
import org.mongodb.scala.bson.conversions.Bson
@@ -21,20 +23,23 @@ abstract class Search[A]()(implicit ct: ClassTag[A]) extends Base[A] {
2123
sort: Bson = Document(),
2224
projection: Bson = Document(),
2325
limit: Int = 0
24-
): Observable[A] = {
25-
{
26+
)(implicit decoder: Decoder[A]): Observable[A] = {
27+
val findObservable = {
2628
if (limit > 0) {
2729
coll.find(filter).sort(sort).projection(projection).limit(limit)
2830
}
2931
else {
3032
coll.find(filter).sort(sort).projection(projection)
3133
}
32-
}.map(doc => documentToObject[A](doc))
34+
}
35+
findObservable.map(doc => documentToObject[A](doc))
3336
}
3437

35-
def findById(oid: ObjectId): Observable[A] = find(equal(DatabaseProvider.ObjectIdKey, oid))
38+
def findById(oid: ObjectId)(implicit decoder: Decoder[A]): Observable[A] = {
39+
find(equal(DatabaseProvider.ObjectIdKey, oid))
40+
}
3641

37-
def find(name: String, value: Any): Observable[A] = {
42+
def find(name: String, value: Any)(implicit decoder: Decoder[A]): Observable[A] = {
3843
find(equal(name, value))
3944
}
4045

@@ -46,8 +51,14 @@ abstract class Search[A]()(implicit ct: ClassTag[A]) extends Base[A] {
4651
distinct(fieldName, filter).resultList().map(v => fromBson(v).asInstanceOf[S])
4752
}
4853

49-
def findAggregated(pipeline: Seq[Bson], allowDiskUse: Boolean = false): Observable[A] = {
50-
coll.aggregate(pipeline).allowDiskUse(allowDiskUse).map(doc => documentToObject[A](doc)).asInstanceOf[AggregateObservable[A]]
54+
def findAggregated(pipeline: Seq[Bson], allowDiskUse: Boolean = false)(implicit decoder: Decoder[A]): Observable[A] = {
55+
val aggregateObservable = coll.aggregate(pipeline).allowDiskUse(allowDiskUse)
56+
aggregateObservable.map {
57+
case a: A =>
58+
a
59+
case doc =>
60+
documentToObject[A](doc)
61+
}
5162
}
5263

5364
}

src/main/scala/dev/mongocamp/driver/mongodb/pagination/MongoPaginatedAggregation.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import org.mongodb.scala.bson.conversions.Bson
88
import org.mongodb.scala.model.Aggregates
99

1010
import scala.jdk.CollectionConverters._
11+
import dev.mongocamp.driver.mongodb.schema.JsonConverter._
1112

1213
case class MongoPaginatedAggregation[A <: Any](
1314
dao: MongoDAO[A],

src/main/scala/dev/mongocamp/driver/mongodb/pagination/MongoPaginatedFilter.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ package dev.mongocamp.driver.mongodb.pagination
22

33
import dev.mongocamp.driver.mongodb.exception.MongoCampPaginationException
44
import dev.mongocamp.driver.mongodb.{ MongoDAO, _ }
5+
import io.circe.Decoder
6+
import io.circe.generic.auto._
57
import org.mongodb.scala.bson.conversions.Bson
68

7-
case class MongoPaginatedFilter[A <: Any](dao: MongoDAO[A], filter: Bson = Map(), sort: Bson = Map(), projection: Bson = Map(), maxWait: Int = DefaultMaxWait)
8-
extends MongoPagination[A] {
9+
case class MongoPaginatedFilter[A <: Any](dao: MongoDAO[A], filter: Bson = Map(), sort: Bson = Map(), projection: Bson = Map(), maxWait: Int = DefaultMaxWait)(
10+
implicit decoder: Decoder[A]
11+
) extends MongoPagination[A] {
912

1013
def paginate(page: Long, rows: Long): PaginationResult[A] = {
1114
val count = countResult

src/main/scala/dev/mongocamp/driver/mongodb/relation/OneToManyRelationship.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ package dev.mongocamp.driver.mongodb.relation
22

33
import dev.mongocamp.driver.mongodb.{ GenericObservable, MongoDAO }
44
import dev.mongocamp.driver.mongodb.relation.RelationCache.{ addCachedValue, getCachedValue, hasCachedValue }
5+
import io.circe.Decoder
56

6-
case class OneToManyRelationship[A](dao: MongoDAO[A], daoKey: String, useCache: Boolean = true) extends Relationship {
7+
case class OneToManyRelationship[A](dao: MongoDAO[A], daoKey: String, useCache: Boolean = true)(implicit decoder: Decoder[A]) extends Relationship {
78

89
def relatedRecords(value: Any): List[A] = {
910
val key = "%s_%s".format(id, value)

src/main/scala/dev/mongocamp/driver/mongodb/relation/OneToOneRelationship.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package dev.mongocamp.driver.mongodb.relation
22

3-
import dev.mongocamp.driver.mongodb.{ GenericObservable, MongoDAO }
4-
import dev.mongocamp.driver.mongodb.relation.RelationCache.{ addCachedValue, getCachedValue, hasCachedValue }
3+
import dev.mongocamp.driver.mongodb.{GenericObservable, MongoDAO}
4+
import dev.mongocamp.driver.mongodb.relation.RelationCache.{addCachedValue, getCachedValue, hasCachedValue}
5+
import io.circe.Decoder
56

6-
case class OneToOneRelationship[A](dao: MongoDAO[A], daoKey: String, useCache: Boolean = true) extends Relationship {
7+
case class OneToOneRelationship[A](dao: MongoDAO[A], daoKey: String, useCache: Boolean = true)(implicit decoder: Decoder[A]) extends Relationship {
78

89
def relatedRecord(value: Any): Option[A] = {
910
val key = "%s_%s".format(id, value)

0 commit comments

Comments
 (0)