[More Detail] [Collapse All]
Feature: Add api-loader plugin

Sbuilder defines an extension point to add API loader plugins,
implemented as a Ruby class satistfying `api_loader_facade`
-contract.

To use a plugin add an entry to `extend.loaders` array in
`sbuilder.yaml` defining `className` for the plugin, and an entry to
`intrefaces` array refering to the plugin `className`.
features/100-plugin-extension/010-api-loader-plugin.feature
- Background: Implement simple plugin
link

Create Ruby class implementing Sbuilder  API loader interface. This class
defines methods:

- ::configure: set static configuration for the API loader,
  particularly it sets property `definitionToCreate`

- #initiazlize: create new API loader instance
  
- #setFacade method: associate Sbuilder facade with the new API loader instance
  
- #load: invoke API load operation, this operation uses
  configuration property `definitionToCreate` to create a
  defintion with the configure name
features/100-plugin-extension/010-api-loader-plugin.feature:13
Given a directory named "lib"
And a file named "lib/test_api.rb" with:
class TestLoader
  # enable plugin configuration
  # 
  # NOTICE: @logger is not available for static method ::configure
  def self.configure( configuration )
          @@configuration = configuration
          puts "Configured #{configuration}"
  end
  # create loader instance: receives sBuilder options
  def initialize( options={} )
  end
  # Sbuilder frawework calls `setFacede` immediatelly after constructor
  def setFacade( facade )
      @facade = facade
      # create logger with progname 'test'
      @logger = @facade.createLogger( "TestLoader" )
      @logger.info "used facade to access logger" 
  end
  # Load api interface defined in `yamlFileUri`
  def load( yamlFileUri )
      @logger.info "loading configuration from #{yamlFileUri}" 
      isArray = false
      # Create definition 'customer'
      customerDef = @facade.newDefinition( @@configuration['definitionToCreate'] )
      name = @facade.newParameter( 'name', isArray )
      customerDef.addParameter( name )
      @facade.modelDefinition( customerDef )
      # Create operation /customer(put)
      request = @facade.newInterface( '/customer', 'put' )
      input = @facade.newParameterReference( 'input', @@configuration['definitionToCreate'], isArray )
      request.addParameter( input )
      @facade.modelInterface( request )
  end
end # class
When I successfully run `sbuilder.rb init`
And a file named "cnf/sbuilder.yaml" with:
#
# Require the plugin & configure it

extend:
    loaders:
        - gem: test_api.rb
          className: TestLoader
          configuration: 
                val1: 1
                val2: 2
                definitionToCreate: person
#
# Create API loader instance and load API to Sbuilder model

interfaces:
  -  className: TestLoader
     file: interface1.configuration

#
# Default resolver (matching all interfaces)
#
resolvers:
    - url: cnf/example_resolver.yaml
#
# Setup to generate specification code in setup 'example'
#
setups:
   - setupDirectory: example
And a file named "cnf/example_resolver.yaml" with:
# catch all resolver
-    Name: default-relsover
     Matcher: !ruby/regexp /.*/
     Rules: 
      - Matcher: !ruby/regexp /.*/
        Domain: default_domain
- Scenario: Generate requires plugin and loads api instance
link

Use bash to set environment variable `RUBYLIB` to inluce
subdirectory `lib` into ruby $: path.

Observe the generated tla model to  contain:

- data type for 'customer' -definition
- process definition to interface operation '/customer(put)'.
features/100-plugin-extension/010-api-loader-plugin.feature:110
Given I successfully run `bash -c "RUBYLIB=lib sbuilder.rb generate example -l DEBUG"`
Then the stdout should contain:
Configured {\"val1\"=>1, \"val2\"=>2, \"definitionToCreate\"=>\"person\"}
Then a file named "sbuilder.log" should exist
And the file named "sbuilder.log" should contain:
loading configuration from cnf/interface1.configuration
Then a file named "gen/example/tla/model.tla" should exist
And the file named "gen/example/tla/model.tla" should contain:
t_person == [
  name: d_default_domain
]
And the file named "gen/example/tla/model.tla" should contain:
fair process (p__customer_put_="/customer(put)")