Skip to content
This repository has been archived by the owner on Apr 10, 2019. It is now read-only.

Commit

Permalink
#112, feat: Changed structure of transition definition in swagger spe…
Browse files Browse the repository at this point in the history
…cification
  • Loading branch information
slavaschmidt committed Apr 2, 2016
1 parent c158c2d commit de001ac
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 31 deletions.
14 changes: 9 additions & 5 deletions compiler/src/main/scala/de/zalando/apifirst/ast.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ object Http {

def string2verb(name: String): Option[Verb] = verbs find { _.name == name.trim.toUpperCase }

// TODO flesh out this hierarchy
class MimeType(val name: String) extends Expr

case object ApplicationJson extends MimeType("application/json")
Expand All @@ -35,6 +34,10 @@ object Http {

case object SirenJson extends MimeType("application/vnd.siren+json")

case object CollectionJson extends MimeType("application/vnd.collection+json")

case object LdJson extends MimeType("application/ld+json")

case class Body(value: Option[String]) extends Expr

}
Expand All @@ -45,17 +48,18 @@ object Hypermedia {
def name: String
}

type Condition = String
type StateTransitionsTable = Map[State, Map[State, Option[Condition]]]
type Condition = Option[String]
case class TransitionProperties(condition: Condition)
type StateTransitionsTable = Map[State, Map[State, TransitionProperties]]

object State {
def apply(name: String): State = if (Self.name.equalsIgnoreCase(name)) Self else NamedState(name)
def toDot(table: StateTransitionsTable): Seq[String] = {
val transitions = for {
(from, destinations) <- table
(to, condition) <- destinations
(to, props) <- destinations
toNode = if (to == Self) from else to
label = condition.getOrElse("")
label = props.condition.getOrElse("")
transition = s""" "${from.name}" -> "${toNode.name}" [label="$label"];"""
} yield transition
val acceptingNodes = table collect {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import java.net.URI

import de.zalando.apifirst.Application.StrictModel
import de.zalando.apifirst.Domain.Type
import de.zalando.apifirst.Hypermedia.{NamedState, State}
import de.zalando.apifirst.Hypermedia.{NamedState, State, TransitionProperties}
import de.zalando.apifirst.naming.Reference
import de.zalando.swagger.strictModel.SwaggerModel

Expand All @@ -32,8 +32,8 @@ object ModelConverter extends ParameterNaming {
case h if apiCalls.seq.forall { _.handler.packageName == h.handler.packageName } => h.handler.packageName
}
val stateTransitionsTable = model.transitions map { case (fromName, toStates) =>
State(fromName) -> toStates.map { case (toName, condition) =>
State(toName) -> condition
State(fromName) -> toStates.map { case (toName, props) =>
State(toName) -> TransitionProperties(Option(props).flatMap(_.get("condition").map(_.toString)))
}
}
StrictModel(apiCalls, typeDefs.toMap, inlineParameters, discriminators,
Expand Down
16 changes: 6 additions & 10 deletions compiler/src/main/scala/de/zalando/swagger/strictModel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -806,19 +806,15 @@ object strictModel {
trait VendorExtensions { self =>
private[this] val extensions = new mutable.HashMap[String, String]
private[this] val errorMappings = new mutable.HashMap[String, Seq[Class[Exception]]]
private[this] val transitionDefinitions = new mutable.HashMap[String, Map[String, Option[String]]]
private[this] val transitionDefinitions = new mutable.HashMap[String, Map[String, Map[String, Any]]]
@JsonAnySetter
def handleUnknown(key: String, value: Any) {
value match {
case str: String if key.startsWith("x-") =>
extensions += key -> str
case trans: Map[String, Map[String, String]]
case trans: Map[String, Map[String, Map[String, Any]]]
if key.equalsIgnoreCase("x-api-first-transitions") =>
transitionDefinitions ++= trans.map { case (k, v) =>
k -> v.map { case (kk, vv) =>
kk -> Option(vv).filter(_.nonEmpty)
}
}
transitionDefinitions ++= trans
case trans if key.equalsIgnoreCase("x-api-first-transitions") =>
throw new IllegalArgumentException("Malformed transition definitions")
case mapping: Map[_, _] if key.startsWith("x-") =>
Expand All @@ -845,7 +841,7 @@ object strictModel {
}
lazy val vendorExtensions = extensions.toMap
lazy val vendorErrorMappings = errorMappings.toMap
lazy val transitions: Map[String, Map[String, Option[String]]] = transitionDefinitions.toMap
lazy val transitions: Map[String, Map[String, Map[String, Any]]] = transitionDefinitions.toMap
}

type Many[T] = List[T]
Expand All @@ -864,7 +860,6 @@ object strictModel {
type MimeType = String // The MIME type of the HTTP message.
type Title = String
type Description = String
type Condition = String

type SchemesList = ManyUnique[Scheme.Value]
type MediaTypeList = ManyUnique[MimeType]
Expand All @@ -887,7 +882,8 @@ object strictModel {
type Paths = AdditionalProperties[PathItem] with VendorExtensions
type Oauth2Scopes = AdditionalProperties[String]
type Transitions = AdditionalProperties[TargetStates]
type TargetStates = AdditionalProperties[Condition]
type TargetStates = AdditionalProperties[TransitionProp]
type TransitionProp = AdditionalProperties[Any]

type SchemaOrReference[T] = Either[Schema[T], JsonReference]
type SchemaOrBoolean[T] = Either[SchemaOrReference[T], Boolean]
Expand Down
11 changes: 7 additions & 4 deletions compiler/src/test/resources/extensions/hypermedia.ok.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ paths:
description: Something else
x-api-first-transitions:
resource created:
resource updated: "some rule to show the transition"
subresource added: # no rule (always shown)
resource updated:
condition: "some rule to show the transition"
subresource added:
resource updated:
subresource added: "" # empty rule (always true)
self: "non-empty rule"
subresource added:
condition: "" # empty rule (always true)
self:
condition: "non-empty rule"
subresource added:
resource updated:
self:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,11 @@ class ParseVendorExtensionsTest extends FunSpec with MustMatchers {
}
it("should read hypermedia definitions") {
implicit val (uri, swagger) = StrictYamlParser.parse(hypermediaOk)
val expected = Map(
"resource created" ->
Map("resource updated" -> Some("some rule to show the transition"), "subresource added" -> None),
"resource updated" ->
Map("subresource added" -> None, "self" -> Some("non-empty rule")),
"resource deleted" ->
Map("self" -> None),
"subresource added" ->
Map("resource updated" -> None, "self" -> None, "resource deleted" -> None))
val expected = Map("resource created" ->
Map("resource updated" -> Map("condition" -> "some rule to show the transition"), "subresource added" -> null),
"resource updated" -> Map("subresource added" -> Map("condition" -> ""),
"self" -> Map("condition" -> "non-empty rule")), "resource deleted" -> Map("self" -> null),
"subresource added" -> Map("resource updated" -> null, "self" -> null, "resource deleted" -> null))
swagger.transitions.nonEmpty mustBe true
swagger.transitions mustEqual expected
swagger.paths("/").get.responses("200").targetState mustEqual Some("resource created")
Expand Down

0 comments on commit de001ac

Please sign in to comment.