Skip to content

Commit

Permalink
feature(metamodel) Add support for decorators
Browse files Browse the repository at this point in the history
Signed-off-by: jeromesimeon <[email protected]>
  • Loading branch information
jeromesimeon committed Aug 4, 2021
1 parent b7177d8 commit caf0077
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 5 deletions.
6 changes: 6 additions & 0 deletions packages/concerto-core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,19 @@ class ModelFileDownloader {
+ string resolveName()
+ object resolveTypeNames()
+ object enumFieldToMetaModel()
+ object decoratorArgToMetaModel()
+ object decoratorToMetaModel()
+ object decoratorsToMetaModel()
+ object fieldToMetaModel()
+ object relationshipToMetaModel()
+ object enumDeclToMetaModel()
+ object classDeclToMetaModel()
+ object declToMetaModel()
+ object modelToMetaModel()
+ object modelFileToMetaModel()
+ string decoratorArgFromMetaModel()
+ string decoratorFromMetaModel()
+ string decoratorsFromMetaModel()
+ string fieldFromMetaModel()
+ string declFromMetaModel()
+ string ctoFromMetaModel()
Expand Down
2 changes: 1 addition & 1 deletion packages/concerto-core/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
# Note that the latest public API is documented using JSDocs and is available in api.txt.
#

Version 1.0.5 {1af0901bd065706dc1409d1e3482fa48} 2021-07-13
Version 1.0.5 {16fb2d5684ec917532a19428c74f1ebf} 2021-07-13
- Add support for Concerto metamodel with import/export to CTO

Version 1.0.3 {1fe469fe1a79af5d5a4f5ec7dee6b7d4} 2021-06-25
Expand Down
123 changes: 121 additions & 2 deletions packages/concerto-core/lib/introspect/metamodel.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,6 @@ function resolveTypeNames(metaModel, table) {
* @return {object} the metamodel for this field
*/
function enumFieldToMetaModel(ast) {
// console.log(`FIELD ${JSON.stringify(ast)}`);
const field = {};

field.$class = 'concerto.metamodel.EnumFieldDeclaration';
Expand All @@ -350,13 +349,68 @@ function enumFieldToMetaModel(ast) {
return field;
}

/**
* Create metamodel for a decorator argument
* @param {object} ast - the AST for the decorator argument
* @return {object} the metamodel for this decorator argument
*/
function decoratorArgToMetaModel(ast) {
const decoratorArg = {};
switch (ast.type) {
case 'String':
decoratorArg.$class = 'concerto.metamodel.DecoratorString';
decoratorArg.value = ast.value;
break;
case 'Number':
decoratorArg.$class = 'concerto.metamodel.DecoratorNumber';
decoratorArg.value = ast.value;
break;
case 'Boolean':
decoratorArg.$class = 'concerto.metamodel.DecoratorBoolean';
decoratorArg.value = ast.value;
break;
default:
break;
}

return decoratorArg;
}

/**
* Create metamodel for a decorator
* @param {object} ast - the AST for the decorator
* @return {object} the metamodel for this decorator
*/
function decoratorToMetaModel(ast) {
const decorator = {
$class: 'concerto.metamodel.Decorator',
name: ast.name,
};
if (ast.arguments && ast.arguments.list) {
if (!ast.arguments.list[0]) {
decorator.arguments = [];
} else {
decorator.arguments = ast.arguments.list.map(decoratorArgToMetaModel);
}
}
return decorator;
}

/**
* Create metamodel for a list of decorators
* @param {object} ast - the AST for the decorators
* @return {object} the metamodel for the decorators
*/
function decoratorsToMetaModel(ast) {
return ast.map(decoratorToMetaModel);
}

/**
* Create metamodel for a class field
* @param {object} ast - the AST for the field
* @return {object} the metamodel for this field
*/
function fieldToMetaModel(ast) {
// console.log(`FIELD ${JSON.stringify(ast)}`);
const field = {};

// Field name
Expand All @@ -375,6 +429,12 @@ function fieldToMetaModel(ast) {
}
// XXX Can it be missing?
const type = ast.propertyType.name;

// Handle decorators
if (ast.decorators && ast.decorators.length > 0) {
field.decorators = decoratorsToMetaModel(ast.decorators);
}

switch (type) {
case 'Integer':
field.$class = 'concerto.metamodel.IntegerFieldDeclaration';
Expand Down Expand Up @@ -585,6 +645,11 @@ function classDeclToMetaModel(ast) {
}
}

// Handle decorators
if (ast.decorators && ast.decorators.length > 0) {
decl.decorators = decoratorsToMetaModel(ast.decorators);
}

// Class fields
decl.fields = [];
for (let n = 0; n < ast.body.declarations.length; n++) {
Expand Down Expand Up @@ -677,6 +742,53 @@ function modelFileToMetaModel(modelFile, validate) {
return modelToMetaModel(modelFile.ast, validate);
}

/**
* Create decorator argument string from a metamodel
* @param {object} mm - the metamodel
* @return {string} the string for the decorator argument
*/
function decoratorArgFromMetaModel(mm) {
let result = '';
switch (mm.$class) {
case 'concerto.metamodel.DecoratorString':
result += `"${mm.value}"`;
break;
default:
result += `${mm.value}`;
break;
}
return result;
}

/**
* Create decorator string from a metamodel
* @param {object} mm - the metamodel
* @return {string} the string for the decorator
*/
function decoratorFromMetaModel(mm) {
let result = '';
result += `@${mm.name}`;
if (mm.arguments) {
result += '(';
result += mm.arguments.map(decoratorArgFromMetaModel).join(',');
result += ')';
}
return result;
}

/**
* Create decorators string from a metamodel
* @param {object} mm - the metamodel
* @param {string} prefix - indentation
* @return {string} the string for the decorators
*/
function decoratorsFromMetaModel(mm, prefix) {
let result = '';
result += mm.map(decoratorFromMetaModel).join(`\n${prefix}`);
result += `\n${prefix}`;
return result;
}

/**
* Create a field string from a metamodel
* @param {object} mm - the metamodel
Expand All @@ -687,6 +799,9 @@ function fieldFromMetaModel(mm) {
let defaultString = '';
let validatorString = '';

if (mm.decorators) {
result += decoratorsFromMetaModel(mm.decorators, ' ');
}
if (mm.$class === 'concerto.metamodel.RelationshipDeclaration') {
result += '-->';
} else {
Expand Down Expand Up @@ -782,6 +897,10 @@ function fieldFromMetaModel(mm) {
*/
function declFromMetaModel(mm) {
let result = '';
if (mm.decorators) {
result += decoratorsFromMetaModel(mm.decorators, '');
}

if (mm.isAbstract) {
result += 'abstract ';
}
Expand Down
6 changes: 6 additions & 0 deletions packages/concerto-core/test/data/model/person.cto
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,13 @@ concept Address identified {
o Boolean isPrivate default=false
}

@Address("x",1,"y","foo","z",true)
@Address2()
@Address3
concept USAddress extends Address {
@Zip("x",1,"y","foo","z",true)
@Zip2()
@Zip3
o Integer zip4 range=[-365,365]
o Integer zip41 range=[,365]
o Integer zip42 range=[-365,]
Expand Down
84 changes: 83 additions & 1 deletion packages/concerto-core/test/data/model/person.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,47 @@
{
"$class": "concerto.metamodel.ConceptDeclaration",
"name": "USAddress",
"decorators": [
{
"$class": "concerto.metamodel.Decorator",
"name": "Address",
"arguments": [
{
"$class": "concerto.metamodel.DecoratorString",
"value": "x"
},
{
"$class": "concerto.metamodel.DecoratorNumber",
"value": 1
},
{
"$class": "concerto.metamodel.DecoratorString",
"value": "y"
},
{
"$class": "concerto.metamodel.DecoratorString",
"value": "foo"
},
{
"$class": "concerto.metamodel.DecoratorString",
"value": "z"
},
{
"$class": "concerto.metamodel.DecoratorBoolean",
"value": true
}
]
},
{
"$class": "concerto.metamodel.Decorator",
"name": "Address2",
"arguments": []
},
{
"$class": "concerto.metamodel.Decorator",
"name": "Address3"
}
],
"isAbstract": false,
"superType": {
"$class": "concerto.metamodel.TypeIdentifier",
Expand All @@ -241,7 +282,48 @@
},
"name": "zip4",
"isArray": false,
"isOptional": false
"isOptional": false,
"decorators": [
{
"$class": "concerto.metamodel.Decorator",
"name": "Zip",
"arguments": [
{
"$class": "concerto.metamodel.DecoratorString",
"value": "x"
},
{
"$class": "concerto.metamodel.DecoratorNumber",
"value": 1
},
{
"$class": "concerto.metamodel.DecoratorString",
"value": "y"
},
{
"$class": "concerto.metamodel.DecoratorString",
"value": "foo"
},
{
"$class": "concerto.metamodel.DecoratorString",
"value": "z"
},
{
"$class": "concerto.metamodel.DecoratorBoolean",
"value": true
}
]
},
{
"$class": "concerto.metamodel.Decorator",
"name": "Zip2",
"arguments": []
},
{
"$class": "concerto.metamodel.Decorator",
"name": "Zip3"
}
]
},
{
"$class": "concerto.metamodel.IntegerFieldDeclaration",
Expand Down
Loading

0 comments on commit caf0077

Please sign in to comment.