Traits, delegation with by, a sealed trait and a dispatcher

The complete source of traits_processors.ek9, compiled by the EK9 compiler. Shown on traits.html.

#!ek9
defines module site.traits.processors

  defines trait

    CostAssessment
      lowCost() as pure
        <- rtn <- true

    Moniterable
      available() as pure
        <- rtn <- true
      lowCost() as pure
        <- rtn <- false

    Processor with trait of Moniterable, CostAssessment
      process()
        <- response as ProcessingResponse?

      override lowCost() as pure
        <- rtn as Boolean: CostAssessment.lowCost()

    ProcessingResponse allow only StringResponse, StructuredResponse
      result()
        <- rtn as String?

  defines class

    StringResponse with trait of ProcessingResponse as open
      theResponse as String: String()

      StringResponse() as pure
        -> response as String
        theResponse :=: response

      StringResponse() as pure
        this(String())

      override result()
        <- rtn as String: theResponse

      default operator ?

    StructuredResponse is StringResponse
      contentType as String: String()

      StructuredResponse() as pure
        ->
          response as String
          contentType as String
        super(response)
        this.contentType :=: contentType

      StructuredResponse() as pure
        ->
          response as String
        this(response, "text/plain")

      contentType() as pure
        <- rtn as String: contentType

      default operator ?

    SimpleProcessor with trait of Processor

      default SimpleProcessor() as pure

      override process()
        <- response as ProcessingResponse: StringResponse("Simple Message")

    DelegatingProcessor with trait of Processor by proc
      proc as Processor?

      DelegatingProcessor() as pure
        -> processorToUse as Processor
        proc :=? processorToUse

      DelegatingProcessor() as pure
        this(SimpleProcessor())

      override lowCost() as pure
        <- rtn as Boolean: false

      default operator ?

    XMLProcessor with trait of Processor
      override process()
        <- response as ProcessingResponse: StructuredResponse("<tag>Simple Message</tag>", "text/xml")
      override lowCost() as pure
        <- rtn as Boolean: false

    //I've used a slightly different layout here and also used named parameters as an example.
    JSONProcessor with trait of Processor
      override process()
        <- response as ProcessingResponse: StructuredResponse(
          response: `{"name": "John", "age": 31, "city": "New York"}`,
          contentType: "application/json"
        )

    ResultBuilder

      build() as dispatcher
        -> response as ProcessingResponse
        <- rtn as String: response.result()

      build()
        -> response as StringResponse
        <- rtn as String: `"${response.result()}"`

      build()
        -> response as StructuredResponse
        <- rtn as String: `${response.contentType()} (( ${response.result()} ))`

  defines program

    ProcessorTest
      stdout <- Stdout()

      processors <- [ SimpleProcessor(), XMLProcessor(), DelegatingProcessor(JSONProcessor()), JSONProcessor()]

      for processor in processors
        response <- processor.process()
        stdout.println(ResultBuilder().build(response))

Download traits_processors.ek9

Output

"Simple Message"
text/xml (( <tag>Simple Message</tag> ))
application/json (( {"name": "John", "age": 31, "city": "New York"} ))
application/json (( {"name": "John", "age": 31, "city": "New York"} ))