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

Sbuilder defines API loader extension point to import
programmatically interfaces, and type definitions into sbuilder.

To use a plugin add an entry to `extend.loaders` array
`sbuilder.yaml`.  This entry defines `className` of the plugin, and
gives optional class configuration to the plugin. The class is
supposed satistfy `api_loader_facade` -contract.

Interface to load, and plugin used in loading , are defined in
'interfaces' array in sbuilder. An entry in this array defines api
loader invocation using plugin given by className -property.
features/100-plugin-extension/010-api-loader-plugin.feature
- Background: Implement simple plugin
link

Create Ruby class inhering from 'Sbuilder::LoaderPluginRoot' and
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
  
- API loader plugin defines two parameter. One of the
  parameters, 'name' is assigned to a domain, which is also defined
  in the plugin.
  
- #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:18
Given a directory named "lib"
And a file named "lib/test_api.rb" with:
class TestLoader < Sbuilder::LoaderPluginRoot
  # 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, 
  # MUST call super
  def initialize( options={} )
       super( options )
  end
  # Sbuilder frawework calls `setFacede` immediatelly after constructor
  def setFacade( facade )
      @facade = facade
      # create logger with progname 'TestLoader'
      # @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'] )
      domainName = 'name_domain_set_in_plugin'
      name = @facade.newParameter( 'name', isArray )
      # add parameter  'name' in domain 'domainName' to 'customerDef'
      @facade.defineDomain( domainName )
      @facade.addParameter( customerDef, name, domainName )
      @facade.modelDefinition( customerDef )
      # Create operation /customer(put)
      request = @facade.newInterface( '/customer', 'put' )
      input = @facade.newParameterReference( 'input', @@configuration['definitionToCreate'], isArray )
      @facade.addParameter( request, input )
      @facade.modelInterface( request )
  end
end # class
When I successfully run `sbuilder.rb init`
And a file named "cnf/sbuilder.yaml" with:
#
# 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:
# resolver  find domain for input, but NOT for name
# which is assigned domain in API loader 
-    Name: default-relsover
     Matcher: !ruby/regexp /.*/
     Rules: 
      - Matcher: input
        Domain: input_domain
      # - Matcher: name
      #   Domain: name_domain
- Scenario: Use unanmed plugin instance to load API configuration
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:109
Given YAML configuration file `cnf/sbuilder.yaml`
#
# Require the plugin & configure it

extend:
    loaders:
        - gem: test_api.rb
          className: TestLoader
          configuration: 
                val1: 1
                val2: 2
                definitionToCreate: person
Given YAML configuration file `cnf/sbuilder.yaml`
#
# Create API loader instance and load API to Sbuilder model

interfaces:
  -  className: TestLoader
     file: interface1.configuration
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_name_domain_set_in_plugin
]
And the file named "gen/example/tla/model.tla" should contain:
CONSTANTS d_input_domain
And the file named "gen/example/tla/model.tla" should contain:
fair process (p__customer_put_="/customer(put)")
- Scenario: Using nmed plugin instance to load API configuration
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:171
Given YAML configuration file `cnf/sbuilder.yaml`
#
# Require the plugin & configure it

extend:
    loaders:
        - gem: test_api.rb
          className: TestLoader
          configuration: 
                val1: 1
                val2: 2
                definitionToCreate: person
          objects:
             - objectName: pluginObject1
             - objectName: pluginObject2                      
Given YAML configuration file `cnf/sbuilder.yaml`
#
# Create API loader instance and load API to Sbuilder model

interfaces:
      # -  className: TestLoader
     - objectName: pluginObject2
       file: interface1.configuration
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_name_domain_set_in_plugin
]
And the file named "gen/example/tla/model.tla" should contain:
CONSTANTS d_input_domain
And the file named "gen/example/tla/model.tla" should contain:
fair process (p__customer_put_="/customer(put)")