Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vocabulary): vocaulary for map types #755

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/concerto-core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ class MapKeyType extends Decorated {
+ String toString()
+ boolean isKey()
+ boolean isValue()
+ string getNamespace()
}
class MapValueType extends Decorated {
+ void constructor(MapDeclaration,Object) throws IllegalModelException
Expand All @@ -190,6 +191,7 @@ class MapValueType extends Decorated {
+ String toString()
+ boolean isKey()
+ boolean isValue()
+ string getNamespace()
}
+ ModelManager newMetaModelManager()
+ object validateMetaModel()
Expand Down Expand Up @@ -272,6 +274,7 @@ class ScalarDeclaration extends Declaration {
+ boolean isTransaction()
+ boolean isEvent()
+ boolean isConcept()
+ boolean isMapDeclaration()
}
class TransactionDeclaration extends IdentifiedDeclaration {
+ void constructor(ModelFile,Object) throws IllegalModelException
Expand Down
3 changes: 3 additions & 0 deletions packages/concerto-core/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
# Note that the latest public API is documented using JSDocs and is available in api.txt.
#

Version 3.13.2 {8aa6c0e12fe380d694604e3edd965730} 2023-10-18
- Add getNamespace method to kep type and value type of maps
mttrbrts marked this conversation as resolved.
Show resolved Hide resolved

Version 3.13.1 {f5a9a1ea6a64865843a3abb77798cbb0} 2023-10-18
- Add migrate option to DecoratorManager options

Expand Down
6 changes: 4 additions & 2 deletions packages/concerto-core/lib/decoratormanager.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ enum CommandType {

/**
* Which models elements to add the decorator to. Any null
* elements are 'wildcards'.
* elements are 'wildcards'.
*/
concept CommandTarget {
o String namespace optional
o String declaration optional
o String property optional
o String[] properties optional // property and properties are mutually exclusive
o String type optional
o String type optional
o MapElement mapElement optional
}

Expand Down Expand Up @@ -438,6 +438,8 @@ class DecoratorManager {
if (this.falsyOrEqual(target.type, declaration.value.$class)) {
this.applyDecorator(declaration.value, type, decorator);
}
} else {
this.applyDecorator(declaration, type, decorator);
mttrbrts marked this conversation as resolved.
Show resolved Hide resolved
}
} else if (!(target.property || target.properties || target.type)) {
this.applyDecorator(declaration, type, decorator);
Expand Down
8 changes: 8 additions & 0 deletions packages/concerto-core/lib/introspect/mapkeytype.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,14 @@ class MapKeyType extends Decorated {
isValue() {
return false;
}

/**
* Return the namespace of this map key.
* @return {string} namespace - a namespace.
mttrbrts marked this conversation as resolved.
Show resolved Hide resolved
*/
getNamespace() {
return this.modelFile.getNamespace();
}
}

module.exports = MapKeyType;
8 changes: 8 additions & 0 deletions packages/concerto-core/lib/introspect/mapvaluetype.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ class MapValueType extends Decorated {
isValue() {
return true;
}

/**
* Return the namespace of this map value.
* @return {string} namespace - a namespace.
*/
getNamespace() {
return this.modelFile.getNamespace();
}
}

module.exports = MapValueType;
10 changes: 10 additions & 0 deletions packages/concerto-core/lib/introspect/scalardeclaration.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,16 @@ class ScalarDeclaration extends Declaration {
return false;
}

/**
* Returns true if this class is the definition of a map-declaration.
*
* @return {boolean} true if the class is a map-declaration
* @deprecated
*/
isMapDeclaration() {
mttrbrts marked this conversation as resolved.
Show resolved Hide resolved
return false;
}

}

module.exports = ScalarDeclaration;
8 changes: 8 additions & 0 deletions packages/concerto-core/test/introspect/mapdeclaration.js
Original file line number Diff line number Diff line change
Expand Up @@ -750,4 +750,12 @@ describe('MapDeclaration', () => {
declaration.getValue().getParent().should.equal(declaration);
});
});

describe('#getNamespace', () => {
it('should return the correct namespace MapDeclaration Key and Value ', () => {
mttrbrts marked this conversation as resolved.
Show resolved Hide resolved
let declaration = introspectUtils.loadLastDeclaration('test/data/parser/mapdeclaration/mapdeclaration.goodkey.primitive.string.cto', MapDeclaration);
declaration.getKey().getNamespace().should.equal('[email protected]');
declaration.getValue().getNamespace().should.equal('[email protected]');
});
});
});
13 changes: 13 additions & 0 deletions packages/concerto-core/test/introspect/scalardeclaration.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,4 +305,17 @@ describe('ScalarDeclaration', () => {
testClass.isClassDeclaration().should.be.false;
});
});

describe('#isMapDeclaration', () => {
const modelFileName = 'test/data/parser/scalardeclaration.ssn.cto';

beforeEach(() => {
const modelFiles = introspectUtils.loadModelFiles([modelFileName], modelManager);
modelManager.addModelFiles(modelFiles);
});
it('should return false', () => {
const testClass = modelManager.getType('com.testing.SSN');
testClass.isMapDeclaration().should.be.false;
});
});
});
35 changes: 31 additions & 4 deletions packages/concerto-vocabulary/lib/vocabulary.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,42 @@ class Vocabulary {
*/
validate(modelFile) {
const getOwnProperties = (d) => {
// ensures we have a valid return, even for scalars
return d.getOwnProperties?.() ? d.getOwnProperties?.() : [];
// ensures we have a valid return, even for scalars and map-declarations
mttrbrts marked this conversation as resolved.
Show resolved Hide resolved
return d.isMapDeclaration() ? [d.getKey(), d.getValue()] : d.getOwnProperties?.() ? d.getOwnProperties?.() : [];
mttrbrts marked this conversation as resolved.
Show resolved Hide resolved
};

const getPropertyName = (p) => {
if(p.isKey?.()) {
return 'KEY';
} else if(p.isValue?.()) {
return 'VALUE';
} else {
return p.getName();
}
};

const checkProperties = (k, p) => {
mttrbrts marked this conversation as resolved.
Show resolved Hide resolved
const declaration = modelFile.getLocalType(Object.keys(k)[0]);
const property = Object.keys(p)[0];
if(declaration.isMapDeclaration()) {
if (!property.localeCompare('KEY')) {
mttrbrts marked this conversation as resolved.
Show resolved Hide resolved
return true;
} else if(!property.localeCompare('VALUE')) {
mttrbrts marked this conversation as resolved.
Show resolved Hide resolved
return true;
} else {
return false;
}
} else {
return declaration.getOwnProperty(Object.keys(p)[0]);
}

};
const result = {
missingTerms: modelFile.getAllDeclarations().flatMap( d => this.getTerm(d.getName())
? getOwnProperties(d).flatMap( p => this.getTerm(d.getName(), p.getName()) ? null : `${d.getName()}.${p.getName()}`)
? getOwnProperties(d).flatMap( p => this.getTerm(d.getName(), getPropertyName(p)) ? null : `${d.getName()}.${getPropertyName(p)}`)
: d.getName() ).filter( i => i !== null),
additionalTerms: this.content.declarations.flatMap( k => modelFile.getLocalType(Object.keys(k)[0])
? Array.isArray(k.properties) ? k.properties.flatMap( p => modelFile.getLocalType(Object.keys(k)[0]).getOwnProperty(Object.keys(p)[0]) ? null : `${Object.keys(k)[0]}.${Object.keys(p)[0]}`) : null
? Array.isArray(k.properties) ? k.properties.flatMap( p => checkProperties(k, p) ? null : `${Object.keys(k)[0]}.${Object.keys(p)[0]}`) : null
: k ).filter( i => i !== null)
};

Expand Down
25 changes: 19 additions & 6 deletions packages/concerto-vocabulary/lib/vocabularymanager.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,18 @@ class VocabularyManager {
resolveTerms(modelManager, namespace, locale, declarationName, propertyName) {
const modelFile = modelManager.getModelFile(namespace);
const classDecl = modelFile ? modelFile.getType(declarationName) : null;
const property = propertyName ? classDecl ? classDecl.getProperty(propertyName) : null : null;
let property;
if(classDecl && !classDecl.isScalarDeclaration()) {
if(classDecl.isMapDeclaration()) {
mttrbrts marked this conversation as resolved.
Show resolved Hide resolved
if(propertyName === 'KEY') {
property = classDecl.getKey();
} else if(propertyName === 'VALUE') {
property = classDecl.getValue();
}
} else {
property = propertyName ? classDecl ? classDecl.getProperty(propertyName) : null : null;
}
}
return this.getTerms(property ? property.getNamespace() : namespace, locale, property ? property.getParent().getName() : declarationName, propertyName);
}

Expand Down Expand Up @@ -336,19 +347,21 @@ class VocabularyManager {
});
}

decl.getProperties?.().forEach(property => {
const propertyTerms = this.resolveTerms(modelManager, model.getNamespace(), locale, decl.getName(), property.getName());
const propertyNames = decl.getProperties ? decl.getProperties().map(property => property.getName()) : decl.isMapDeclaration ? decl.isMapDeclaration() ? ['KEY', 'VALUE'] : [] : [];
mttrbrts marked this conversation as resolved.
Show resolved Hide resolved
propertyNames.forEach(propertyName => {
const propertyTerms = this.resolveTerms(modelManager, model.getNamespace(), locale, decl.getName(), propertyName);
if (propertyTerms) {
Object.keys(propertyTerms).forEach( term => {
if(term === property.getName()) {
const propertyType = !propertyName.localeCompare('KEY') || !propertyName.localeCompare('VALUE') ? 'mapElement' : 'property';
if(term === propertyName) {
decoratorCommandSet.commands.push({
'$class': `${DC_NAMESPACE}.Command`,
'type': 'UPSERT',
'target': {
'$class': `${DC_NAMESPACE}.CommandTarget`,
'namespace': model.getNamespace(),
'declaration': decl.getName(),
'property': property.getName()
[propertyType]: propertyName
},
'decorator': {
'$class': `${MetaModelNamespace}.Decorator`,
Expand All @@ -370,7 +383,7 @@ class VocabularyManager {
'$class': `${DC_NAMESPACE}.CommandTarget`,
'namespace': model.getNamespace(),
'declaration': decl.getName(),
'property': property.getName()
[propertyType]: propertyName
},
'decorator': {
'$class': `${MetaModelNamespace}.Decorator`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,103 @@ Object {
},
"type": "UPSERT",
},
Object {
"$class": "[email protected]",
"decorator": Object {
"$class": "[email protected]",
"arguments": Array [
Object {
"$class": "[email protected]",
"value": "Address of the vehicle",
},
],
"name": "Term",
},
"target": Object {
"$class": "[email protected]",
"declaration": "Address",
"namespace": "[email protected]",
},
"type": "UPSERT",
},
Object {
"$class": "[email protected]",
"decorator": Object {
"$class": "[email protected]",
"arguments": Array [
Object {
"$class": "[email protected]",
"value": "Registered address of the vehicle owner",
},
],
"name": "Term_description",
},
"target": Object {
"$class": "[email protected]",
"declaration": "Address",
"namespace": "[email protected]",
},
"type": "UPSERT",
},
Object {
"$class": "[email protected]",
"decorator": Object {
"$class": "[email protected]",
"arguments": Array [
Object {
"$class": "[email protected]",
"value": "View Address of vehicle owner",
},
],
"name": "Term_tooltip",
},
"target": Object {
"$class": "[email protected]",
"declaration": "Address",
"namespace": "[email protected]",
},
"type": "UPSERT",
},
Object {
"$class": "[email protected]",
"decorator": Object {
"$class": "[email protected]",
"arguments": Array [
Object {
"$class": "[email protected]",
"value": "vin of the vehicle",
},
],
"name": "Term",
},
"target": Object {
"$class": "[email protected]",
"declaration": "Address",
"mapElement": "KEY",
"namespace": "[email protected]",
},
"type": "UPSERT",
},
Object {
"$class": "[email protected]",
"decorator": Object {
"$class": "[email protected]",
"arguments": Array [
Object {
"$class": "[email protected]",
"value": "address of the vehicle",
},
],
"name": "Term",
},
"target": Object {
"$class": "[email protected]",
"declaration": "Address",
"mapElement": "VALUE",
"namespace": "[email protected]",
},
"type": "UPSERT",
},
Object {
"$class": "[email protected]",
"decorator": Object {
Expand Down
7 changes: 6 additions & 1 deletion packages/concerto-vocabulary/test/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ asset Vehicle identified by vin {
o Color color
}

map Address {
o String
o String
}

asset Truck extends Vehicle {
o Double weight
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@ declarations:
- Truck: A lorry
description: A heavy goods vehicle
- Color: A colour
- Milkfloat
- Milkfloat
- Address: Address of the vehicle
description: Registered address of the vehicle owner
tooltip: View Address of vehicle owner
properties:
- keyy: mispelled KEY spelling
6 changes: 5 additions & 1 deletion packages/concerto-vocabulary/test/[email protected]_en.voc
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ declarations:
tooltip: Truck weight
- horsePower: The horse power of the truck
description: The horse power of the truck
tooltip: Truck HP
tooltip: Truck HP
- Address: Registered address of the vehicle
properties:
- KEY: vin of the vehicle
- VALUE: address of the vehicle
5 changes: 4 additions & 1 deletion packages/concerto-vocabulary/test/[email protected]_fr.voc
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ namespace: [email protected]
declarations:
- Vehicle: Véhicule
properties:
- vin: Le numéro d'identification du véhicule (NIV)
- vin: Le numéro d'identification du véhicule (NIV)
- Address: Adresse
properties:
- KEY: NIV du véhicule
Loading