Skip to content

Commit dee4360

Browse files
authored
Merge pull request #9 from zalando/#8-Configuration-in-controller
#8, refactor: Added configuration parameter to the controller
2 parents 0fcdb21 + 8032b47 commit dee4360

37 files changed

+228
-66
lines changed

api/src/main/scala/de/zalando/play/controllers/PlayBodyParsing.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,11 @@ object PlayBodyParsing extends PlayBodyParsing {
9191
bytes: ByteString, mediaType: Option[MediaType]
9292
)(implicit tag: ClassTag[T]): T = {
9393
val mimeTypeName = mimeType(mediaType)
94-
val jacksonParser: Parser[T] =
95-
byteString => jacksonMapper(mimeTypeName).readValue(bytes.toArray, tag.runtimeClass.asInstanceOf[Class[T]])
94+
val jacksonParser: Parser[T] = byteString =>
95+
if (tag.runtimeClass == classOf[String]) new String(byteString.toArray).asInstanceOf[T]
96+
else if (tag.runtimeClass == classOf[BinaryString]) BinaryString.byteArray2binaryString(byteString.toArray).asInstanceOf[T]
97+
else if (tag.runtimeClass == classOf[Base64String]) Base64String.fromBytes(byteString.toArray).asInstanceOf[T]
98+
else jacksonMapper(mimeTypeName).readValue(bytes.toArray, tag.runtimeClass.asInstanceOf[Class[T]])
9699
// TODO default play parsers could be used here as well
97100
val parser = customParsers.find(_._1 == mimeTypeName).map(_._2).getOrElse {
98101
jacksonParser

api/src/main/scala/de/zalando/play/controllers/WriterFactories.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
88
*/
99
object WriterFactories {
1010
private val jsonFactory = new JsonFactory()
11-
1211
/**
1312
* Contains proper Jackson Factories for different mime types
1413
* JsonFactory is a default

api/src/main/scala/de/zalando/play/controllers/stringWrappers.scala

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,16 @@ case class Base64String(value: String) {
1313

1414
object Base64String {
1515
implicit def string2base64string(s: String): Base64String =
16-
Base64String(new String(Base64.getEncoder.encode(s.getBytes)))
16+
fromBytes(s.getBytes)
17+
1718
implicit def base64string2string(s: Base64String): String =
18-
new String(Base64.getDecoder.decode(s.value))
19+
new String(toBytes(s))
20+
21+
def toBytes(s: Base64String): Array[Byte] =
22+
Base64.getDecoder.decode(s.value)
23+
24+
def fromBytes(b: Array[Byte]): Base64String =
25+
Base64String(new String(Base64.getEncoder.encode(b)))
1926
}
2027

2128
case class BinaryString(value: Array[Byte])

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import sbt._
44
val PlayVersion = "2.5.4"
55
val Scala10 = "2.10.5"
66
val Scala11 = "2.11.8"
7-
val ProjectVersion = "0.1.13"
7+
val ProjectVersion = "0.1.14"
88

99
val deps = new Dependencies(PlayVersion, ProjectVersion)
1010

play-scala-generator/src/main/resources/model.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ package {{main_package_suffix}} {
5151
{{/for}}
5252

5353
{{for enum in enums}}
54-
case class {{enum.name}}(value: {{enum.type_name}}) {
54+
case class {{enum.name}}(value: {{enum.type_name}}) extends AnyVal {
5555
override def toString = value.toString
5656
}
5757
{{/for}}

play-scala-generator/src/main/resources/play_scala_controller.mustache

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ import {{import.name}}
1313
{{for controller in controllers}}
1414
package {{controller.effective_package}} {
1515
16-
class {{controller.controller}} extends {{controller.base}} {
16+
class {{controller.controller}} @Inject() (lifecycle: ApplicationLifecycle, config: ConfigurationProvider) extends {{controller.base}} {
17+
{{controller.start_comment}}
18+
{{controller.constructor_code}}
19+
{{controller.end_comment}}
1720
{{for method in controller.methods}}
1821
val {{method.method}} = {{method.action}} { {{for sp in method.single_parameter}}({{sp.field_name}}: {{sp.type_name}}) =>{{/for}}{{if method.multiple_parameters}}input: ({{for p in method.multiple_parameters}}{{p.type_name}}{{if p.isNotLast}}, {{/if}}{{/for}}) =>
1922
val ({{for p in method.multiple_parameters}}{{p.field_name}}{{if p.isNotLast}}, {{/if}}{{/for}}) = input{{else}}{{if method.single_parameter}} {{else}} _ => {{/if}} {{/if}}

play-scala-generator/src/main/scala/de/zalando/apifirst/generators/controllersStep.scala

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import de.zalando.apifirst.StringUtil._
1010
import de.zalando.apifirst.generators.DenotationNames._
1111
import de.zalando.apifirst.naming.Reference
1212
import org.slf4j.Logger
13+
import ControllersCommons._
1314

1415
/**
1516
* @author slasch
1617
* @since 31.12.2015.
1718
*/
1819
trait CallControllersStep extends EnrichmentStep[ApiCall]
19-
with ControllersCommons with SecurityCommons with ActionResults with ParameterData {
20+
with SecurityCommons with ActionResults with ParameterData {
2021

2122
def log: Logger
2223

@@ -183,17 +184,19 @@ trait CallControllersStep extends EnrichmentStep[ApiCall]
183184

184185
}
185186

186-
object PlayScalaControllerAnalyzer extends ControllersCommons {
187+
object PlayScalaControllerAnalyzer {
187188

188189
case class UnmanagedPart(marker: ApiCall, relevantCode: Seq[String])
189190

190191
val controllerImports = Seq(
191192
"play.api.mvc.{Action, Controller}",
192193
"play.api.data.validation.Constraint",
194+
"play.api.inject.{ApplicationLifecycle,ConfigurationProvider}",
193195
"de.zalando.play.controllers._",
194196
"PlayBodyParsing._",
195197
"PlayValidations._",
196-
"scala.util._"
198+
"scala.util._",
199+
"javax.inject._"
197200
)
198201

199202
def analyzeController(calls: Seq[ApiCall], codeParts: Map[String, Seq[String]]): Map[ApiCall, UnmanagedPart] =
@@ -217,7 +220,9 @@ object PlayScalaControllerAnalyzer extends ControllersCommons {
217220
}.toSeq.flatten
218221

219222
def collectImplementations(currentVersion: Seq[String], start: String, end: String): Map[String, Seq[String]] = {
220-
val actionIndexes = currentVersion.zipWithIndex.filter(_._1.trim.startsWith(start)).map { case (line, idx) => line.replace(start, "") -> idx }
223+
val actionIndexes = currentVersion.zipWithIndex.filter(_._1.trim.startsWith(start)).map {
224+
case (line, idx) => line.replace(start, "") -> idx
225+
}
221226
val codeParts = actionIndexes map {
222227
case (action, idx) =>
223228
val fromStart = currentVersion.drop(idx)
@@ -269,12 +274,15 @@ trait ParameterData {
269274

270275
}
271276

272-
trait ControllersCommons {
277+
object ControllersCommons {
273278

274279
val controllersSuffix = "Action"
275280
val formParserSuffix = "ParseForm"
276281

277282
val eof = "// ----- End of unmanaged code area for action "
278283
val sof = "// ----- Start of unmanaged code area for action "
279284

285+
val ceof = "// ----- End of unmanaged code area for constructor "
286+
val csof = "// ----- Start of unmanaged code area for constructor "
287+
280288
}

play-scala-generator/src/main/scala/de/zalando/apifirst/generators/playScala.scala

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import de.zalando.apifirst.generators.DenotationNames.DenotationTable
77
import PlayScalaControllerAnalyzer._
88
import de.zalando.apifirst.StringUtil
99
import org.slf4j.LoggerFactory
10+
import ControllersCommons._
1011

1112
import scala.collection.Iterable
1213

@@ -106,6 +107,7 @@ class ScalaGenerator(
106107
nonEmptyTemplate(fileName, packageName, templateName, currentController)
107108
}
108109

110+
//noinspection ScalaStyle
109111
private def nonEmptyTemplate(fileName: String, packageName: String, templateName: String, currentController: String): String = {
110112

111113
assert(packageName.contains('-') == packageName.contains('`'), packageName)
@@ -144,7 +146,14 @@ class ScalaGenerator(
144146
val securityExtractors = ReShaper.filterByType("security_extractors", denotationTable)
145147
val extractors = ReShaper.groupByType(securityExtractors.toSeq).toMap
146148

147-
val codeParts = collectImplementations(currentController.split("\n"), sof, eof)
149+
val controllerLines = currentController.split("\n")
150+
val codeParts = collectImplementations(controllerLines, sof, eof)
151+
val constructors = collectImplementations(controllerLines, csof, ceof)
152+
153+
val constructorCode = constructors map {
154+
case (k, v) =>
155+
k -> v.filterNot(l => l.trim.startsWith(csof) || l.trim.startsWith(ceof)).mkString("\n")
156+
} withDefaultValue ""
148157

149158
val unmanagedParts = analyzeController(modelCalls, codeParts)
150159

@@ -169,7 +178,8 @@ class ScalaGenerator(
169178
"form_parsers_required" -> formParsersRequired
170179
)
171180

172-
val controllersList = PlayScalaControllersGenerator.controllers(modelCalls, unmanagedParts, pckg, deadCode)(denotationTable)
181+
val controllersList = PlayScalaControllersGenerator.
182+
controllers(modelCalls, unmanagedParts, pckg, deadCode, constructorCode)(denotationTable)
173183

174184
val stdImports = standardImports(modelTypes).map(i => Map("name" -> i))
175185

@@ -262,7 +272,7 @@ object PlayScalaControllersGenerator {
262272
val securityTraitSuffix = "Security"
263273

264274
def controllers(allCalls: Seq[ApiCall], unmanagedParts: Map[ApiCall, UnmanagedPart], packageName: String,
265-
deadCode: Map[String, String])(table: DenotationTable): Iterable[Map[String, Object]] = {
275+
deadCode: Map[String, String], constructorCode: Map[String, String])(table: DenotationTable): Iterable[Map[String, Object]] = {
266276
allCalls groupBy { c =>
267277
(c.handler.packageName, c.handler.controller)
268278
} map {
@@ -280,13 +290,17 @@ object PlayScalaControllersGenerator {
280290
case (k, v) =>
281291
Map("name" -> k, "code" -> v)
282292
}
293+
val controllerName = escape(controller._2)
283294
Map(
284295
"effective_package" -> packageName,
285-
"controller" -> escape(controller._2),
296+
"controller" -> controllerName,
286297
"base" -> escape(controller._2 + baseControllersSuffix),
287298
"methods" -> methods,
288299
"security_trait" -> securityTrait,
289-
"dead_code" -> deadCodeParts
300+
"dead_code" -> deadCodeParts,
301+
"start_comment" -> (csof + controllerName),
302+
"end_comment" -> (ceof + controllerName),
303+
"constructor_code" -> constructorCode(controller._2)
290304
)
291305
}
292306
}

play-scala-generator/src/test/resources/expected_results/controllers/basic_auth_api_yaml.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import play.api.mvc.{Action, Controller}
33

44
import play.api.data.validation.Constraint
55

6+
import play.api.inject.{ApplicationLifecycle,ConfigurationProvider}
7+
68
import de.zalando.play.controllers._
79

810
import PlayBodyParsing._
@@ -11,6 +13,8 @@ import PlayValidations._
1113

1214
import scala.util._
1315

16+
import javax.inject._
17+
1418

1519
/**
1620
* This controller is re-generated after each change in the specification.
@@ -19,7 +23,9 @@ import scala.util._
1923

2024
package basic.auth.api.yaml {
2125

22-
class BasicAuthApiYaml extends BasicAuthApiYamlBase {
26+
class BasicAuthApiYaml @Inject() (lifecycle: ApplicationLifecycle, config: ConfigurationProvider) extends BasicAuthApiYamlBase {
27+
// ----- Start of unmanaged code area for constructor BasicAuthApiYaml
28+
// ----- End of unmanaged code area for constructor BasicAuthApiYaml
2329
val get = getAction { _ =>
2430
// ----- Start of unmanaged code area for action BasicAuthApiYaml.get
2531
NotImplementedYet

play-scala-generator/src/test/resources/expected_results/controllers/basic_polymorphism_yaml.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import play.api.mvc.{Action, Controller}
33

44
import play.api.data.validation.Constraint
55

6+
import play.api.inject.{ApplicationLifecycle,ConfigurationProvider}
7+
68
import de.zalando.play.controllers._
79

810
import PlayBodyParsing._
@@ -11,6 +13,8 @@ import PlayValidations._
1113

1214
import scala.util._
1315

16+
import javax.inject._
17+
1418

1519
/**
1620
* This controller is re-generated after each change in the specification.
@@ -19,7 +23,12 @@ import scala.util._
1923

2024
package basic_polymorphism.yaml {
2125

22-
class Basic_polymorphismYaml extends Basic_polymorphismYamlBase {
26+
class Basic_polymorphismYaml @Inject() (lifecycle: ApplicationLifecycle, config: ConfigurationProvider) extends Basic_polymorphismYamlBase {
27+
// ----- Start of unmanaged code area for constructor Basic_polymorphismYaml
28+
lifecycle.addStopHook {() =>
29+
Future.successful(println("Shutting down"))
30+
}
31+
// ----- End of unmanaged code area for constructor Basic_polymorphismYaml
2332
val put = putAction { (dummy: PutDummy) =>
2433
// ----- Start of unmanaged code area for action Basic_polymorphismYaml.put
2534
NotImplementedYet

0 commit comments

Comments
 (0)