ALMOsT is an AgiLe MOdel Transformation framework for JavaScript
ALMOsT tries to reduce the complexity involved in MDD (Model Driven Development) and in particular Model Transformations. With ALMOsT it is possible to start writing new transformations by understanding just few simple concepts.
ALMOsT is build uped these design principles:
- No installation It is possible to use the framework instantly, with no installations.
- No new language It is possible to start using the framework by just knowing JavaScript.
- Fast start-up It is possible to create a minimum viable model editor and model transformation in a very short time.
- Parallel development It is possible to work in team on different aspects of the same sprint, e.g., by adding a new concept to the model editor, and the corresponding generative rules to the model to model transformation and model to text transformation in parallel.
- Customized generation While ALMOsT provides a predefined set of output "formats", it is possible to customize the generated output following the necessity of the developer.
ALMOsT is developed in modules. The two underlying components are:
ALMOsT also gives you a set of plugins which can be installed separately:
Here are the few concepts needed to write a model transformation using ALMOst.
The input, an many times the output, of a model transformation is a model.
{
"elements": [
...
],
"relations": [
...
]
}
The only requirements set by ALMOsT are:
- A valid Model is a JSON object
- A valid Model has a field called
elements
, which is an Array. Anything item of this array will be considered as an Element in the model. - A valid Model has a field called
relations
, which is an Array. Anything item of this array will be considered as a Relationship between elements in the model.
No other requirements are mandated in order to start using ALMOsT.
Rules are the building block of a transformation.
createRule(
/* Activation Function */
function (model) { /* Condition */ },
/* Action Function */
function (model) { /* Action */ }
)
They are composed of two functions:
- The Activation Function which decides if the rules is going to be enabled on the specific input.
- The Action Function which, given the current input, generates a partial output.
There are 3 types of Rules:
- Model Rules which are invokes once on the entire model
createRule( function (model) { /* Condition */ }, function (model) { /* Action */ } )
- Element Rules which are invokes once on each element in the model (i.e. the items of the
elements
array)createRule( function (element, model) { /* Condition */ }, function (element, model) { /* Action */ } )
- Relation Rules which are invokes once on each relationship in the model (i.e. the items of the
relations
array)createRule( function (relation, model) { /* Condition */ }, function (relation, model) { /* Action */ } )
N.B. there is no guarantees on the execution order of transformation rules.
All the partial results, generated by the transformation rules, are merged togheter by means of a reducer.
ALMOsT Provides 3 default reduction policies:
- Model To Model
m2m
, in this case the rules output is going to be merged as if it was a partial model (i.e. it contains two fields namedelements
andrelations
which content is going to be concatenated) - Model To Text
m2t
, in this case the rules output is going to be merged as if it was a partial "file system". Each partial result is anObject
in which each field is anObject
itself describing a folder or a file:- Files are
Object
s having 2 fields:name
aString
which contains the name of the filecontent
aString
which contains the name of the file Only one rules should generate a specific file
- Folders are
Object
s having 3 fields (:name
aString
which contains the name of the folderisFolder
always set totrue
children
anArray
containingString
s, each one referencing a the key of another filed in the to "file system like"Object
Multiple rules can generate the same folder, but only one rule should setname
andisFolder
, the elements ofchildren
will be concatenated.
- Files are
- Model To ALMOsT
m2a
the same asm2m
, but Elements and Relations should follow the extra requirements defined in A bit or restrictions for extra power.
var createTransformer = require('almost').createTransformer,
createRule = require('almost').createRule;
var transform = createTransformer({
model: [
createRule(
function (model) { /* Condition */ },
function (model) { /* Action */ }
)
],
element: [
createRule(
function (element, model) { /* Condition */ },
function (element, model) { /* Action */ }
)
],
relation: [
createRule(
function (relation, model) { /* Condition */ },
function (relation, model) { /* Action */ }
)
]
}, 'm2m');
var inputModel = {
elements: [
...
],
relations: [
...
],
}
var output = transform(input);
While there are minimal restrictions imposed on the Model, in particular the structure of an Element or a Relationship, ALMOsT has a suggested structure to follow.
See the documentation of almost-extend.
Following this structure not just enables the use of almost-extend, but also enables the use of the m2a
reducer, which enables the developer to generate the same Element in multiple rules.
Elements generated in different rules are matched by id
and their attributes
, and matadata
, are merged using the mergeOrSingle
policty defined in almost-core.
Under this policy Array
attributes are concatenated, while Object
attributes are reducersively merged with the same policy.
- ICWE2018-Tutorial contains a simple example written during a Tutorial at ICWE 2018.
- IFMLEdit.org contains multiple examples of transformations.