Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ object ModelBuilder {
state: State)
extends Entity(fqn, entityType) {
val abstractEntityName = "Abstract" + fqn.name

val handlerName = fqn.name + "Handler"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I wonder if it would be nicer to keep them in fqn form here, but that's not for this PR)

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ object ValueEntitySourceGenerator {
generatedSources += File(
s"$packagePath/${valueEntity.abstractEntityName}.scala",
abstractEntity(valueEntity, service))
//FIXME add Handler and Provider
generatedSources += File(s"$packagePath/${valueEntity.handlerName}.scala", handler(valueEntity, service))
//FIXME add Provider

generatedSources.result()
}
Expand Down Expand Up @@ -86,6 +87,54 @@ object ValueEntitySourceGenerator {
|""".stripMargin
}

private[codegen] def handler(valueEntity: ModelBuilder.ValueEntity, service: ModelBuilder.EntityService): String = {
val stateType = valueEntity.state.fqn.name
val packageName = valueEntity.fqn.parent.scalaPackage
val valueEntityName = valueEntity.fqn.name
implicit val imports =
generateImports(
Seq(valueEntity.state.fqn) ++
service.commands.map(_.inputType) ++
service.commands.map(_.outputType),
valueEntity.fqn.parent.scalaPackage,
otherImports = Seq(
"com.akkaserverless.scalasdk.valueentity.CommandContext",
"com.akkaserverless.scalasdk.valueentity.ValueEntity",
"com.akkaserverless.scalasdk.impl.valueentity.ValueEntityHandler",
"com.akkaserverless.scalasdk.impl.valueentity.ValueEntityHandler.CommandHandlerNotFound"),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be wrong. In View and Actions we used the corresponding javasdk exception instead of defining a new in scalasdk. It's not something seen by the user. In that we we don't need to catch-convert-throw.

packageImports = Seq(service.fqn.parent.scalaPackage),
semi = false)

val commandCases = service.commands
.map { cmd =>
val methodName = cmd.name
val inputType = typeName(cmd.inputType)
s"""|case "$methodName" =>
| entity.${lowerFirst(methodName)}(state, command.asInstanceOf[$inputType])
|""".stripMargin
}

s"""|package $packageName
|
|$imports
|
|/**
| * A value entity handler that is the glue between the Protobuf service <code>CounterService</code>
| * and the command handler methods in the <code>Counter</code> class.
| */
|class ${valueEntityName}Handler(entity: ${valueEntityName}) extends ValueEntityHandler[$stateType, ${valueEntityName}](entity) {
| def handleCommand(commandName: String, state: $stateType, command: Any, context: CommandContext): ValueEntity.Effect[_] = {
| commandName match {
| ${Format.indent(commandCases, 6)}
|
| case _ =>
| throw new ValueEntityHandler.CommandHandlerNotFound(commandName)
| }
| }
|}
|""".stripMargin
}

def generateImplementationSkeleton(
valueEntity: ModelBuilder.ValueEntity,
service: ModelBuilder.EntityService): File = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,38 @@ class ValueEntitySourceGeneratorSuite extends munit.FunSuite {
|""".stripMargin)
}

test("it can generate a value entity handler implementation") {
val str = handler(testData.valueEntity(domainParent), testData.simpleEntityService(apiParent))
assertNoDiff(
str,
s"""package com.example.service.domain
|
|import com.akkaserverless.scalasdk.impl.valueentity.ValueEntityHandler
|import com.akkaserverless.scalasdk.impl.valueentity.ValueEntityHandler.CommandHandlerNotFound
|import com.akkaserverless.scalasdk.valueentity.CommandContext
|import com.akkaserverless.scalasdk.valueentity.ValueEntity
|import com.example.service
|import com.external.Empty
|
|/**
| * A value entity handler that is the glue between the Protobuf service <code>CounterService</code>
| * and the command handler methods in the <code>Counter</code> class.
| */
|class MyValueEntityHandler(entity: MyValueEntity) extends ValueEntityHandler[MyState, MyValueEntity](entity) {
| def handleCommand(commandName: String, state: MyState, command: Any, context: CommandContext): ValueEntity.Effect[_] = {
| commandName match {
| case "Set" =>
| entity.set(state, command.asInstanceOf[service.SetValue])
|
| case "Get" =>
| entity.get(state, command.asInstanceOf[service.GetValue])
|
| case _ =>
| throw new ValueEntityHandler.CommandHandlerNotFound(commandName)
| }
| }
|}
|""".stripMargin)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ package com.akkaserverless.scalasdk.impl.valueentity
import com.akkaserverless.scalasdk.valueentity.CommandContext
import com.akkaserverless.scalasdk.valueentity.ValueEntity

object ValueEntityHandler {
final case class CommandHandlerNotFound(commandName: String) extends RuntimeException
}

abstract class ValueEntityHandler[S, E <: ValueEntity[S]](val entity: E) {
def handleCommand(commandName: String, state: S, command: Any, context: CommandContext): ValueEntity.Effect[_]
}