Artifact generators

Artifact generators are contained in Wizzi plugins and are exposed to the Wizzi factory implementing the wizzi-plugin.factoryPlugin API.

The wizzi-plugin.factoryPlugin.getArtifactGenerator(artifactKey) method returns a wizzi-plugin.artifactGenerator interface for generating the requested `artifactName`.

wizzi-plugin.artifactGenerator API


                    
1 {
2 func gen
3 { model
4 | api-ref wizzi-plugin.wizziModel
5 | POJO
6 { ctx
7 api-ref wizzi.artifact.genContext
8 callback

Plugins authors are free to implement this interface with their preferred tools.

In this documentation section we describe solutions that the wizzi factory has taken for its own artifact generators.

Wizzi factory standard location for artifact generators

Artifact generators should have a standard location in the plugin package.


                    
1 ...
2 {package-name}
3 package.json
4 ...
5 lib
6 artifacts
7 {wfschema-name}
8 {artifact-name}
9 gen
10 main.js

The file 'main.js' is the module that exposes the wizzi-plugin.artifactGenerator interface for the artifact of key: {wfschema-name}/{artifact-name}.

This artifact key must be unique in the plugins configuration of the wizzi.WizziFactory instance that is executing the generation.

Example of 'generator' attribute in a 'wfjob'

The {wfschema-name}/{artifact-name} artifact key is the value to be declared in the `generator` attribute of the `artifact` element of a 'wfjob' ITTF document.

Use of an artifact generator in a Wizzi job

                    
1 wfjob {job-name}
2 ...
3 line {line-name}
4 artifact {artifact-generation-description}
5 ...
6 generator {wfschema-name}/{artifact-name}
7 ...
Implementation

An artifact generator produces a buffer of text characters. The production is driven by models contained in the parameters passed to the generator.

An artifact generator receives three parameters:


                    
1 func gen
2 { model
3 | api-ref wizzi-plugin.wizziModel
4 | POJO
5 { ctx
6 api-ref wizzi.artifact.genContext
7 callback
  • A model can be a Wizzi Model or a POJO, and represent the main context of the artifact generation.
  • An instance of the wizzi.artifact.genContext class that contains
    • An in-memory buffer where the generated text is written sequentially using write and write line methods.
    • A data context that may contain zero or many secondary context models, Wizzi Models or POJO.
    • Some helper functions for text indentation, interpolation and error management.
  • A callback function that a succesfull generation must call passing, as a second parameter, an instance of the wizzi.artifact.genContext with the text buffer containing the generated artifact

Artifact generations are write based, using the write statements of the wizzi.artifact.genContext, or template based.

Code generation by term rewriting

The mTree loader, implemented by the wizzi-mtree.loader.loadMTree API, is a powerfull model composer and transformer. Model transformations can be chained: an output mTree can become the input context for the next mTree loading. A 'wfjob' model can orchestrate any number of cascading transformations. The models passed to the artifact generator are the final models, ready for generating the textual artifact.

A template based generation, that uses the mTree loader, can be, indeed, more a code generation by term rewriting than a textual code generation. When mTrees are loaded into Wizzi Models, that can apply types and validations, and can programmatically modify the model, we have a tool for efficiently enabling any extension of the target language, easily implementing partial classes or any other modular aspect or rewrite rule.

Language schemas and language artifact generators

Focusing on the generation of the textual content of an artifact, we must treat of a class of Wizzi Model types that is specific for the production of code targeting the synthax of a programming languages (PL).

A language schema defines a tree structure that an associated language artifact generator can transform in a targeting PL code. It can be viewd as a profile of a PL Grammar that can be implemented partially, with some of its symbols stereotyped. The schema developer should try to find the optimal balance between ease of use and completeness and define the proper approximation of the schema in respect to the PL grammar.

Must be said that language schema is a concept. A language schema is like any other wizzi schema and a language artifact is like any other artifact generator. The production of specific tools for creating language schemas and artifacts could be undertaken in the future.

The wizzi factory, that is generated by the wizzi factory, uses some language schemas for its generations:

  • The `js` schema in the wizzi-js plugin.
  • The `html`, `css` and `md` schemas in the wizzi-html plugin.

Template based artifact generation

Language schema Wizzi models are template formats for Wizzi factory template based artifact generations.

`js` ittf document

                    
1 module
2 kind jsfile
3 class Horse
4 super Animal
5 ctor
6 param name
7 base name
8 m say
9 log 'Hiiii i am ', this.name
10 m create
11 static
12 param name
13 return
14 new Horse
15 @ name

Almost every ittf node maps to a node type of the javascripts AST. And ittf nodes can be template node commands and can contain expressions.

Example of template based implementation of the wizzi-plugin.artifactGenerator API

In this dummy example, a 'js' ittf document template, named 'datalayer/adapters.js.ittf' is transformed in the javascript textual code of a fictitious datalayer adapter component.

This example artifact generator makes use internaly of a 'js' language artifact generator, named 'js/module'. The Wizzi model that it receives as first parameter, has been loaded in previous steps, and becomes the mTreeBuilUpContext object for loading the mTree of the `js` ITTF document template. It must be a Wizzi Model of type 'rdbms' otherwise an error is returned in the callback.

The `js` source ITTF document is loaded, and transformed in a textual artifact, calling the 'loadModelAndGenerateArtifact' method of the wizzi.WizziFactory class, exposed in the property 'wizziFactory' of the 'ctx' parameter (an instance of the wizzi.artifact.genContext class).


                    
1 module
2 kind jsfile
3 var path = require('path')
4 var md = module.exports = {}
5 var myname = 'artifact rdbms.adapters.main';
6 set md.gen
7 function
8 { model
9 { ctx
10 callback
11 # check the model is a Wizzi Model of type 'rdbms'
12 if model.wzElement !== 'rdbms'
13 return
14 callback
15 _ctx.error
16 @ myname + " error: the model paramater should be an 'rdbms' Wizzi Model"
17 @ model
18 # build the artifact template path, it is a js ittf document in a sub folder
19 var ittfTemplatePath
20 _ path.join
21 @ __dirname
22 @ 'ittf'
23 @ 'datalayer'
24 @ 'adapters.js.ittf'
25 # call the wizzifactory method for loading a language Wizzi Model and
26 # generate a language artifact from it. Pass the input model in the
27 # mTreeBuildUpContext property of the request object argument.
28 # The 'js' schema of the template model is detected by its filename.
29 _ ctx.wizziFactory.loadModelAndGenerateArtifact
30 @ ittfTemplatePath
31 {
32 @ mTreeBuildUpContext model
33 @ 'js/module'
34 function
35 param err
36 param artifactText
37 if err
38 # invoke the callback on error, passing back the loadModelAndGenerateArtifact error
39 return
40 _ callback
41 err
42 # write the artifactText into the genContext buffer
43 _ ctx.write(artifactText)
44 # invoke the callback on success, passing back the genContext
45 _ callback(null, ctx)
The genContext object

The interface of the gencontext object


                    
1 class genContext
2 #
3 # Set line indentation to a given value
4 m forceIndent
5 param value
6 #
7 # Increase line indentation
8 m indent
9 param value
10 #
11 # Decrease line indentation
12 m deindent
13 param value
14 #
15 # Add a named value to the interpolation context
16 m a
17 param name
18 param value
19 #
20 # Add a named value from the interpolation context
21 m g
22 param name
23 #
24 # Remove a named value from the interpolation context
25 m r
26 param name
27 #
28 # Write a text with interpolation and line feed
29 m w
30 param text
31 #
32 # Write a text with interpolation without line feed
33 m write
34 param text
35 #
36 # throw a NodeError exception
37 m error
38 param message
39 param node
40 #
41 # throw an ArtifactGenerationError exception
42 m artifactGenerationError
43 param message
44 param location
45 param node
Sample artifact generator

Code write artifact generator sample


                    
1 module
2 kind jsfile
3 var md = module.exports = {}
4 var myname = 'artifact rdbms.sqltables.main';
5 set md.gen
6 function
7 param model
8 param ctx
9 param callback
10 if model.wzElement !== 'rdbms'
11 return
12 callback
13 _ctx.error
14 @ myname + " error: the model paramater should be an 'rdbms' Wizzi Model"
15 @ model
16 $foreach table in model.tables
17 _ ctx.a('TABLE', table.wzName)
18 _ ctx.w('declare table TABLE')
19 ...
20 _ callback(null, ctx)
Internal artifacts

The wizzi-core plugin exports some useful artifacts. We already have seen the artifacts for the psedo models

  • Json
  • Xml
  • Text

There are also these others core artifacts

  • json/export
  • xml/export
  • ittf/document

"json/export" builtin artifact

The json/export builtin artifact can be used in a Wizzi job, to save the JSON representation ofa Wizzi model, when its Wizzi schemadeclares the `export-to json` element.

Sample wfjob artifact element using the json/export artifact.

                    
1 wfjob
2 ...
3 artifact json export of model sample.form.ittf
4 src sample.form.ittf
5 schema form
6 generator json/export
7 extension json
"xml/export" builtin artifact

The xml/export builtin artifact can be used in a Wizzi job, to save the xml representation ofa Wizzi Model when its Wizzi schemadeclares the `export-to xml` element.

Sample wfjob artifact element using the xml/export artifact.

                    
1 wfjob
2 ...
3 artifact xml export of model sample.form.ittf
4 src sample.form.ittf
5 schema form
6 generator xml/export
7 extension xml
"ittf/document" builtin artifact

The 'ittf/document' builtin artifact exports the ittf representation of a loaded mTree. This allow the buildup of ittf documents using the mTree loader for merging sources and contexts.

Sample wizzi job using the 'ittf/document' generator.

                    
1 wfjob
2 model styles
3 src styles.json.ittf
4 schema json
5 model layout
6 src layout.json.ittf
7 schema json
8 model optionsforms
9 src options.form.ittf
10 schema form
11 line ui
12 artifact ittf document of model options-page.html.ittf
13 src options-page.html.ittf
14 schema ittf
15 generator ittf/document
16 extension ittf
17 model-ref styles
18 model-ref layout
19 model-ref optionsforms