Commit 035ba4b1 authored by Nicolas Biri's avatar Nicolas Biri
Browse files

Merge branch 'es2015'

parents 1ca31469 31118f49
v0.6:
- Migration to jsmf-core 0.4
v0.7:
- ES6 migration
v0.6:
- Migration to jsmf-core 0.4
......@@ -7,118 +7,116 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
Authors : Nicolas Biri
*/
'use strict';
'use strict'
// model imports
var JSTL = require('../../index');
var Transformation = JSTL.Transformation;
var NAV = require('jsmf-magellan');
var Model = require('jsmf-core').Model;
const JSTL = require('../../index')
const Transformation = JSTL.Transformation
const NAV = require('jsmf-magellan')
const Model = require('jsmf-core').Model
// other imports
var _ = require('lodash');
var inspect = require('eyes').inspector({
maxLength: 50000
});
const _ = require('lodash')
const inspect = require('eyes').inspector({maxLength: 50000})
// Metamodels
var MMI = require('./MMArduinoML');
var MMO = require('./MMAbstractCode');
const MMI = require('./MMArduinoML')
const MMO = require('./MMAbstractCode')
// input file
var input = require('./MArduinoML').switchExample;
var output = new Model('Out');
const input = require('./MArduinoML').switchExample
const output = new Model('Out')
var module = new Transformation();
const transfo = new Transformation()
module.addRule({
in: function(x) { return NAV.allInstancesFromModel(MMI.App, x)},
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.App, x),
out: function(i) {
var app = MMO.App.newInstance();
this.assign(app, 'structural', [i]);
this.assign(app, 'behavioural', [i]);
return [app];
var app = MMO.App.newInstance()
this.assign(app, 'structural', [i])
this.assign(app, 'behavioural', [i])
return [app]
}
});
})
module.addRule({
in: function(x) { return NAV.allInstancesFromModel(MMI.App, x)},
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.App, x),
out: function(i) {
var s = MMO.StructuralConcerns.newInstance();
this.assign(s, 'alias', i.brick);
this.assign(s, 'pinMode', i.brick);
return [s];
var s = MMO.StructuralConcerns.newInstance()
this.assign(s, 'alias', i.brick)
this.assign(s, 'pinMode', i.brick)
return [s]
}
});
})
module.addRule({
in: function(x) { return NAV.allInstancesFromModel(MMI.Brick, x)},
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.Brick, x),
out: function(i) {
return [MMO.BrickAlias.newInstance({name: i.name, pin: i.pin})];
return [MMO.BrickAlias.newInstance({name: i.name, pin: i.pin})]
}
});
})
module.addRule({
in: function(x) { return NAV.allInstancesFromModel(MMI.Sensor, x)},
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.Sensor, x),
out: function(i) {
return [MMO.PinMode.newInstance({name: i.name, mode: MMO.IO.INPUT})];
return [MMO.PinMode.newInstance({name: i.name, mode: MMO.IO.INPUT})]
}
});
})
module.addRule({
in: function(x) { return NAV.allInstancesFromModel(MMI.Actuator, x)},
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.Actuator, x),
out: function(i) {
return [MMO.PinMode.newInstance({name: i.name, mode: MMO.IO.OUTPUT})];
return [MMO.PinMode.newInstance({name: i.name, mode: MMO.IO.OUTPUT})]
}
});
})
module.addRule({
in: function(x) { return NAV.allInstancesFromModel(MMI.App, x)},
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.App, x),
out: function(i) {
var b = MMO.BehaviouralConcerns.newInstance();
b.timeConfig = MMO.TimeConfig.newInstance({initialTime: 0, debounce: 200});
this.assign(b, 'stateFunction', i.state);
this.assign(b, 'mainLoop', i.initial);
return [b];
var b = MMO.BehaviouralConcerns.newInstance()
b.timeConfig = MMO.TimeConfig.newInstance({initialTime: 0, debounce: 200})
this.assign(b, 'stateFunction', i.state)
this.assign(b, 'mainLoop', i.initial)
return [b]
}
});
})
module.addRule({
in: function(x) { return NAV.allInstancesFromModel(MMI.State, x)},
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.State, x),
out: function(i) {
var t = i.transition[0];
var t = i.transition[0]
var s = MMO.StateFunction.newInstance({
name: i.name,
next: t.next[0].name,
readOn: t.sensor[0].name,
read: t.value
});
this.assign(s, 'write', i.action);
return [s];
})
this.assign(s, 'write', i.action)
return [s]
}
});
})
module.addRule({
in: function(x) { return NAV.allInstancesFromModel(MMI.State, x)},
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.State, x),
out: function(i) {
return [MMO.MainLoop.newInstance({ init: i.name })];
return [MMO.MainLoop.newInstance({ init: i.name })]
}
});
})
module.addRule({
in: function(x) { return NAV.allInstancesFromModel(MMI.Action, x)},
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.Action, x),
out: function(i) {
return [MMO.Write.newInstance({
return [MMO.Write.newInstance({
on: i.actuator[0].name,
value: i.value
})];
})]
}
});
})
// launch transformation
var log = module.apply(input, output, false);
const log = transfo.apply(input, output, false)
_.forEach(NAV.allInstancesFromModel(MMO.App, output), function(x) {console.log(x.toCode())});
_.forEach(NAV.allInstancesFromModel(MMO.App, output), x => console.log(x.toCode()))
......@@ -113,7 +113,9 @@ transformation.addRule(Member2Male);
transformation.addRule(Member2FeMale);
//Apply all rules in the models and resolve references, actual transformation execution
// Apply all rules in the models and resolve references, actual transformation execution
transformation.apply(Mi.ma, Mo);
// Useless, used in test to see if debug mode is ok
transformation.apply(Mi.ma, undefined, true)
module.exports.result = Mo;
'use strict';
var JSTL = require('../../index');
var JSMF = require('jsmf-core');
var _ = require('lodash');
var Model = JSMF.Model;
var Class = JSMF.Class;
var Graph = new Class('Graph');
var Node = new Class('Node', [], {name: String});
Graph.addReference('nodes', Node);
var Edge = new Class('Edge', [], {name: String, sourcee: String, target: String});
Graph.addReference('edges', Edge);
var GraphModel = new Model('GraphModel', {}, Graph, true);
var modelToGraph = new JSTL.Transformation();
var elementName = {
name: 'elementName',
map: function(m) {
var result = new JSTL.Mapping();
var elems = _.flatten(_.values(m.modellingElements));
_.forEach(elems, function(x, i) {
result.map(x, x.conformsTo().__name + '_' + i);
})
return result;
}};
modelToGraph.addHelper(elementName);
modelToGraph.addRule({
name: 'Generate nodes',
in: function(m) {return _.flatten(_.values(m.modellingElements));},
out: function (x) {
var n = new Node();
_.forEach(x.conformsTo().attributes, function(aName) {
var value = x[aName];
n[aName] = value === undefined ? undefined : value.toString();
});
n.name = n.name || this.helpers.elementName.valuesFor(x)[0];
return [n];
}
});
modelToGraph.addRule({
name: 'Generate edges',
in: function(m) {return _.flatten(_.values(m.modellingElements));},
out: function (x) {
var edges = [];
for (var rName in x.conformsTo().references) {
_.forEach(x[rName], function(r) {
var e = new Edge();
e.name = rName;
e.source = JSMF.jsmfId(x);
e.target = JSMF.jsmfId(r);
edges.push(e);
});
}
return edges;
}
});
module.exports = JSMF.modelExport(GraphModel);
module.exports.toGraph = function(source) {
var result = new Model();
var graph = new Graph();
modelToGraph.apply(source, result);
graph.nodes = result.modellingElements.Node || [];
graph.edges = result.modellingElements.Edge || [];
result.add(graph)
return result;
}
......@@ -13,22 +13,20 @@ Contributors: G. Garcia-Frey
- Multiple input/output models
- Hide the complex object for input
*/
'use strict';
'use strict'
var _ = require('lodash');
var JSMF = require('jsmf-core');
const _ = require('lodash')
const JSMF = require('jsmf-core')
/** @constuctor
* Initiate a transformation module.
*/
function Transformation(rules, helpers) {
var rs = [];
_.forEach(rules, function(x) {rs.push(x);});
this.rules = rs;
var hs = [];
_.forEach(helpers, function(x) {hs.push(x);});
this.helpers = hs;
this.rules = []
this.helpers = []
_.forEach(rules, x => this.addRule(x))
_.forEach(helpers, x => this.addHelper(x))
}
/** Add a transformation rule to a transformation module.
......@@ -40,12 +38,12 @@ function Transformation(rules, helpers) {
* @param {string} r.name - An optional name for the rule, not used yet.
*/
Transformation.prototype.addRule = function(r) {
if (_.every(['in', 'out'], function(x) {return _.has(r, x);})) {
this.rules.push(r);
if (_.every(['in', 'out'], x => _.has(r, x))) {
this.rules.push(r)
} else {
throw new Error('Invalid rule:' + r);
throw new Error(`Invalid rule: ${r}`)
}
};
}
/** Add a helper to a transformation module.
......@@ -54,24 +52,24 @@ Transformation.prototype.addRule = function(r) {
* @param {string} h.name - the name of the helper, that will be used to reference the helper when we need it.
*/
Transformation.prototype.addHelper = function(h) {
if (_.every(['map', 'name'], function(x) {return _.has(h, x);})) {
this.helpers.push(h);
if (_.every(['map', 'name'], x => _.has(h, x))) {
this.helpers.push(h)
} else {
throw new Error('Invalid helper:' + h);
throw new TypeError(`Invalid helper: ${h}`)
}
};
}
function Context() {
this.generated = new Mapping();
this.helpers = {};
this.referencesResolutions = [];
this.generationLog = new Mapping();
this.generated = new Map()
this.helpers = {}
this.referencesResolutions = []
this.generationLog = new Map()
}
Context.prototype.addResolution = function(r) {this.referencesResolutions.push(r);};
Context.prototype.addResolution = function(r) {this.referencesResolutions.push(r)}
Context.prototype.assign = function(element, relationName, populators) {
this.addResolution(new ReferenceResolution(element, relationName, populators));
this.addResolution(new ReferenceResolution(element, relationName, populators))
}
/** @constructor
......@@ -84,27 +82,26 @@ Context.prototype.assign = function(element, relationName, populators) {
*/
function Rule(selection, out, name) {
/** @member {function} in */
this.in = selection;
this.in = selection
/** @member {function} out */
this.out = out;
this.out = out
/** @member {string} name */
this.name = name;
this.name = name
}
function runRule(rule, context, inputModel, outputModel, debug) {
var selection = rule.in.call(context, inputModel);
const selection = rule.in.call(context, inputModel)
_.forEach(selection, function(e) {
var generated = rule.out.call(context, e, inputModel);
context.generated.map(e, generated);
const generated = rule.out.call(context, e, inputModel)
const value = (context.generated.get(e) || [])
context.generated.set(e, value.concat(generated))
if (debug) {
_.forEach(generated, function(x) {
context.generationLog.map(x, {rule: rule, source: e});
});
context.generationLog.set(x, {rule, source: e})
})
}
_.forEach(generated, function(x) {
outputModel.addModellingElement(x);
});
});
_.forEach(generated, x => outputModel.addModellingElement(x))
})
}
/** @constructor
......@@ -112,13 +109,13 @@ function runRule(rule, context, inputModel, outputModel, debug) {
* @param {string} name - the name of the helper, that will be used to reference the helper when we need it.
*/
function Helper(generation, name) {
this.map = generation;
this.name = name;
this.map = generation
this.name = name
}
function runHelper(helper, context, inputModel, outputModel) {
var generated = helper.map.call(context, inputModel);
context.helpers[helper.name] = generated;
const generated = helper.map.call(context, inputModel)
context.helpers[helper.name] = generated
}
/** @constructor
......@@ -127,23 +124,23 @@ function runHelper(helper, context, inputModel, outputModel) {
* @param {Object[]} populators - the input model elements that should be resolved to populate the relation.
*/
function ReferenceResolution(element, relationName, populators) {
this.source = element;
this.relationName = relationName;
this.target = populators;
this.source = element
this.relationName = relationName
this.target = populators
}
function runResolution(resolution, generated) {
var relationType = resolution.source.conformsTo().getAllReferences()[resolution.relationName].type;
var referenceFunctionName = 'add' + resolution.relationName[0].toUpperCase() + resolution.relationName.slice(1);
const relationType = resolution.source.conformsTo().getAllReferences()[resolution.relationName].type
const referenceFunctionName = 'add' + resolution.relationName[0].toUpperCase() + resolution.relationName.slice(1)
_.each(resolution.target, // get the type of the target(s) of the relation element in the input model in order to...
function(elem) {
var values = generated.valuesFor(elem) || [];
_.each(values, function(target) {
const values = generated.get(elem) || []
_.each(values, target => {
if (relationType === JSMF.JSMFAny || relationType === undefined || hasClass(target, relationType)) {
resolution.source[referenceFunctionName](target);
resolution.source[referenceFunctionName](target)
}
});
});
})
})
}
/** Apply a trsnformation on an input model, and put generated elements in a given ouput model.
......@@ -152,62 +149,17 @@ function runResolution(resolution, generated) {
* @param {boolean} debug - Store additional information during the transformation.
*/
Transformation.prototype.apply = function(inputModel, outputModel, debug) {
var ctx = new Context();
outputModel = outputModel || new JSMF.Model('TransformationOutput');
_.forEach(this.helpers, function(h) {
runHelper(h, ctx, inputModel, outputModel);
});
_.forEach(this.rules, function(r) {
runRule(r, ctx, inputModel, outputModel, debug);
});
_.forEach(ctx.referencesResolutions, function(r) {
runResolution(r, ctx.generated);
});
return ctx;
const ctx = new Context()
outputModel = outputModel || new JSMF.Model('TransformationOutput')
_.forEach(this.helpers, h => runHelper(h, ctx, inputModel, outputModel))
_.forEach(this.rules, r => runRule(r, ctx, inputModel, outputModel, debug))
_.forEach(ctx.referencesResolutions, r => runResolution(r, ctx.generated))
return ctx
}
var hasClass = function (x, type) {
var types = type instanceof Array ? type : [type];
return _.some(x.conformsTo().getInheritanceChain(),
function (c) {return _.includes(types, c)});
}
function Mapping() {
// aberration, we should use ES6 Map ASAP
}
Mapping.prototype.findEntry = function(k) {
return _.find(this[JSMF.jsmfId(k)], function(x) {return x.key === k;});
}
Mapping.prototype.valuesFor = function(k) {
var entry = this.findEntry(k);
if (entry !== undefined) {return entry.values;}
const types = type instanceof Array ? type : [type]
return _.some(x.conformsTo().getInheritanceChain(), c => _.includes(types, c))
}
Mapping.prototype.map = function(k, v) {
var key = JSMF.jsmfId(k);
if (key === undefined) {
throw new Error('Invalid key for mapping: ' + k);
}
var entry = this.findEntry(k);
if (entry === undefined) {
entry = {key: k, values: []};
if (this[key] === undefined) {
this[key] = [entry];
} else {
this[key].push(entry);
}
}
v = v instanceof Array ? v : [v];
entry.values = entry.values.concat(v);
}
module.exports = {
Mapping: Mapping,
Helper: Helper,
Rule: Rule,
Transformation: Transformation
};
module.exports = {Helper, Rule, Transformation}
{
"name": "jsmf-jstl",
"version": "0.6.0",
"version": "0.8.0",
"description": "Model transformation for JSTL",
"main": "index.js",
"directories": {
......@@ -23,13 +23,12 @@
"author": "Jean-Sebastien Sottet <jean-sebastien.sottet@list.lu> (http://www.list.lu/)",
"license": "MIT",
"dependencies": {
"lodash": "~4.1.0",
"object-hash": "~0.9.2",
"jsmf-core": "git+ssh://git@git.list.lu:jsmf/jsmf-core.git#0.4.0"
"lodash": "^4.1.0",
"jsmf-core": "git+ssh://git@git.list.lu:jsmf/jsmf-core.git#0.6.0"
},
"devDependencies": {
"should": "~7.1.1",
"eyes": "~0.1.8",
"jsmf-magellan": "git+ssh://git@git.list.lu:jsmf/jsmf-magellan.git#refactored"
"should": "^7.1.1",
"eyes": "^0.1.8",
"jsmf-magellan": "git+ssh://git@git.list.lu:jsmf/jsmf-magellan.git#0.4.0"
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment