Skip to content

Commit

Permalink
Supporting trait family
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigogdea committed Apr 13, 2020
1 parent db6b62c commit 609d389
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 35 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,17 @@ You can also add tags asociated to the Event:
```scala
val eventAdapter = EventAdapterFactory.adapt[Type4](withManifest = "SomeEvent", Set("Tag_1", "Tag_2"))
```
Traits famlily (`sealed trait`), aka: sum types, are mapped automatically:
```scala
sealed trait InvoceLineType
case object ProductLine extends InvoiceLineType
...
case class InvoiceLine(lineType: InvoceLineType, ...)
case class InvoiceLineAdded(line: InvoiceLine)
...
implicit val conf = MacroConfiguration(discriminator = "_type", typeNaming = TypeNaming.SimpleName)
val eventAdapter = EventAdapterFactory.adapt[InvoceLineAdded](withManifest = "InvoiceLineAdded")
```

## Persistence Id
By default the persistence id has the following form: `<Aggregate>-<Id>`, and the aggregate will be the name of the journal collection.
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ lazy val rxmongoVersion = "0.20.3"
lazy val commonSettings = Seq(
name := "akka-reactivemongo-plugin",
organization := "null-vector",
version := "1.3.6",
version := "1.3.7",
scalaVersion := scala213,
crossScalaVersions := supportedScalaVersions,
scalacOptions := Seq(
Expand Down
46 changes: 13 additions & 33 deletions core/src/test/scala/org/nullvector/EventAdapterFactorySpec.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.nullvector

import akka.actor.ActorSystem
import org.nullvector.domin._
import org.scalatest.Matchers._
import org.scalatest._
import reactivemongo.api.bson.{BSONDocument, BSONDocumentHandler, BSONDocumentReader, BSONDocumentWriter, BSONReader, BSONString, BSONValue, BSONWriter, Macros}
import reactivemongo.api.bson.MacroConfiguration.Aux
import reactivemongo.api.bson.{BSON, BSONDocument, BSONDocumentHandler, BSONDocumentReader, BSONDocumentWriter, BSONReader, BSONString, BSONValue, BSONWriter, FieldNaming, MacroConfiguration, MacroOptions, Macros, TypeNaming}

import scala.util.{Success, Try}

Expand Down Expand Up @@ -59,8 +61,8 @@ class EventAdapterFactorySpec extends FlatSpec {

val eventAdapter = EventAdatpterFactory.adapt[I]("Ied", justForTestTags)

eventAdapter.tags("A") should contain ("TagA")
eventAdapter.tags("x") should contain ("TagN")
eventAdapter.tags("A") should contain("TagA")
eventAdapter.tags("x") should contain("TagN")
val anInstance = I(K("k"))
eventAdapter.payloadToBson(anInstance)
.getAsOpt[BSONDocument]("k").get
Expand Down Expand Up @@ -88,39 +90,17 @@ class EventAdapterFactorySpec extends FlatSpec {
payload.m.head._2 shouldBe "Value_A"
}

}

case class A(b: B, c: C, d: D, js: Seq[J])

case class B(f: Set[F], g: G)

case class C(s: String, m: Map[String, Seq[J]])

case class D(i: Int, m: Map[String, H] = Map.empty)

case class F(maybeC: Option[C])

case class G(ds: List[D])
it should "mapping sealed trit familly" in {
val distanceFromEarthAndMars = PlanetDistanceBetweenEarth(and = Mars, kilometers = 209050000.0)

case class H(d: BigDecimal)
implicit val conf: Aux[MacroOptions] = MacroConfiguration(discriminator = "_type", typeNaming = TypeNaming.SimpleName)
val eventAdapter = EventAdatpterFactory.adapt[PlanetDistanceBetweenEarth]("x")

case class J(s: String)

case class I(k: K)

case class K(s: String)

case class L(m: Map[Day, String], day: Day)

sealed trait Day

object Day {
def apply(name: String): Day = name match {
case "Monday" => Monday
case "Sunday" => Sunday
val document = eventAdapter.payloadToBson(distanceFromEarthAndMars)
document.getAsOpt[BSONDocument]("and").get.getAsOpt[String]("_type").get should be ("Mars")
eventAdapter.bsonToPayload(document).and should be (Mars)
}

}

case object Monday extends Day

case object Sunday extends Day
61 changes: 61 additions & 0 deletions core/src/test/scala/org/nullvector/domin/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.nullvector

package object domin {

case class A(b: B, c: C, d: D, js: Seq[J])

case class B(f: Set[F], g: G)

case class C(s: String, m: Map[String, Seq[J]])

case class D(i: Int, m: Map[String, H] = Map.empty)

case class F(maybeC: Option[C])

case class G(ds: List[D])

case class H(d: BigDecimal)

case class J(s: String)

case class I(k: K)

case class K(s: String)

case class L(m: Map[Day, String], day: Day)

sealed trait Day

object Day {
def apply(name: String): Day = name match {
case "Monday" => Monday
case "Sunday" => Sunday
}
}


case object Monday extends Day

case object Sunday extends Day

case class PlanetDistanceBetweenEarth(and: SolarPlanet, kilometers: Double)

sealed trait SolarPlanet

case object Mercury extends SolarPlanet

case object Venus extends SolarPlanet

case object Earth extends SolarPlanet

case object Mars extends SolarPlanet

case object Jupiter extends SolarPlanet

case object Saturn extends SolarPlanet

case object Uranus extends SolarPlanet

case object Neptune extends SolarPlanet

}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ private object EventAdapterMacroFactory {
(caseType: context.universe.Type): org.nullvector.Tree[context.universe.Type] = {
import context.universe._

def isSupprtedTrait(aTypeClass: ClassSymbol) = aTypeClass.isTrait && aTypeClass.isSealed && !aTypeClass.fullName.startsWith("scala")

def extaracCaseClassesFromSupportedTypeClasses(classType: Type): List[Type] = {
if (supportedClassTypes.contains(classType.typeSymbol.fullName)) classType.typeArgs.collect {
case argType if argType.typeSymbol.asClass.isCaseClass => List(classType, argType)
Expand All @@ -95,11 +97,14 @@ private object EventAdapterMacroFactory {
caseType.decls.toList
.collect { case method: MethodSymbol if method.isCaseAccessor => method.returnType }
.collect {
case aType if aType.typeSymbol.asClass.isCaseClass => List(extractCaseTypes(context)(aType))
case aType if aType.typeSymbol.asClass.isCaseClass || isSupprtedTrait(aType.typeSymbol.asClass) => List(extractCaseTypes(context)(aType))
case aType => extaracCaseClassesFromSupportedTypeClasses(aType).map(arg => extractCaseTypes(context)(arg))
}.flatten
)
}
else if (isSupprtedTrait(caseType.typeSymbol.asClass)) {
Tree(caseType, caseType.typeSymbol.asClass.knownDirectSubclasses.map(aType => extractCaseTypes(context)(aType.asClass.toType)).toList)
}
else Tree.empty
}

Expand Down

0 comments on commit 609d389

Please sign in to comment.