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

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);
}
} 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.
*/
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() {
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 ', () => {
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
return d.isMapDeclaration() ? [d.getKey(), d.getValue()] : d.getOwnProperties?.() ? d.getOwnProperties?.() : [];
};

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

const checkProperties = (k, p) => {
const declaration = modelFile.getLocalType(Object.keys(k)[0]);
const property = Object.keys(p)[0];
if(declaration.isMapDeclaration()) {
if (!property.localeCompare('KEY')) {
return true;
} else if(!property.localeCompare('VALUE')) {
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()) {
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'] : [] : [];
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