Skip to content

Commit

Permalink
feat(vocabulary) : support multiple terms per concept/property (accor…
Browse files Browse the repository at this point in the history
…dproject#664)

* feat(vocabulary) : support multiple terms per concept/property

Signed-off-by: Dan Selman <[email protected]>
Signed-off-by: sanketshevkar <[email protected]>

* feat(vocabulary): resolved bug for properties and added more test cases (accordproject#666)

* feat(vocabulary): resolved bug for properties and added more test cases

Signed-off-by: sanketshevkar <[email protected]>

* feat(vocabulary): fix to support vocab attributes without '.'

Signed-off-by: sanketshevkar <[email protected]>

---------

Signed-off-by: sanketshevkar <[email protected]>

* feat(vocabulary): old breaking test fixed (accordproject#667)

* feat(vocabulary): resolved bug for properties and added more test cases

Signed-off-by: sanketshevkar <[email protected]>

* feat(vocabulary): fix to support vocab attributes without '.'

Signed-off-by: sanketshevkar <[email protected]>

* feat(vocabulary): old breaking test fixed

Signed-off-by: sanketshevkar <[email protected]>

---------

Signed-off-by: sanketshevkar <[email protected]>

* chore(vocabulary): merge conflict resolution

Signed-off-by: sanketshevkar <[email protected]>

---------

Signed-off-by: Dan Selman <[email protected]>
Signed-off-by: sanketshevkar <[email protected]>
Co-authored-by: sanket Shevkar <[email protected]>
Co-authored-by: sanketshevkar <[email protected]>
Co-authored-by: Matt Roberts <[email protected]>
  • Loading branch information
4 people authored Jul 23, 2023
1 parent a8f797b commit ac70543
Show file tree
Hide file tree
Showing 9 changed files with 14,698 additions and 4,489 deletions.
16,562 changes: 12,332 additions & 4,230 deletions package-lock.json

Large diffs are not rendered by default.

27 changes: 24 additions & 3 deletions packages/concerto-vocabulary/lib/vocabulary.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,40 @@ class Vocabulary {
* Gets the term for a concept, enum or property
* @param {string} declarationName the name of a concept or enum
* @param {string} [propertyName] the name of a property (optional)
* @param {string} [identifier] the identifier of the term (optional)
* @returns {string} the term or null if it does not exist
*/
getTerm(declarationName, propertyName) {
getTerm(declarationName, propertyName, identifier) {
const decl = this.content.declarations.find(d => Object.keys(d)[0] === declarationName);
if(!decl) {
return null;
}
if(!propertyName) {
return decl[declarationName];
return identifier ? decl[identifier] : decl[declarationName];
}
else {
const property = decl.properties ? decl.properties.find(d => d[propertyName]) : null;
return property ? property[propertyName] : null;
return property ? identifier ? property[identifier] : property[propertyName] : null;
}
}

/**
* Gets the terms for a concept, enum or property
* @param {string} declarationName the name of a concept or enum
* @param {string} [propertyName] the name of a property (optional)
* @returns {string} the term or null if it does not exist
*/
getElementTerms(declarationName, propertyName) {
const decl = this.content.declarations.find(d => Object.keys(d)[0] === declarationName);
if(!decl) {
return null;
}
if(!propertyName) {
return decl;
}
else {
const property = decl.properties ? decl.properties.find(d => d[propertyName]) : null;
return property;
}
}

Expand Down
186 changes: 143 additions & 43 deletions packages/concerto-vocabulary/lib/vocabularymanager.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,32 @@ class VocabularyManager {
* @param {string} locale the BCP-47 locale identifier
* @param {string} declarationName the name of a concept or enum
* @param {string} [propertyName] the name of a property (optional)
* @param {string} [identifier] the identifier of the term (optional)
* @returns {string} the term or null if it does not exist
*/
resolveTerm(modelManager, namespace, locale, declarationName, propertyName) {
resolveTerm(modelManager, namespace, locale, declarationName, propertyName, identifier) {
const modelFile = modelManager.getModelFile(namespace);
const classDecl = modelFile ? modelFile.getType(declarationName) : null;
const property = propertyName ? classDecl ? classDecl.getProperty(propertyName) : null : null;
return this.getTerm(property ? property.getNamespace() : namespace, locale, property ? property.getParent().getName() : declarationName, propertyName);
return this.getTerm(property ? property.getNamespace() : namespace, locale, property ? property.getParent().getName() : declarationName, propertyName, identifier);
}

/**
* Resolve the terms for a property, looking up terms from a more general vocabulary
* if required, and resolving properties using an object manager, allowing terms defined
* on super types to be automatically resolved.
* @param {ModelManager} modelManager the model manager
* @param {string} namespace the namespace
* @param {string} locale the BCP-47 locale identifier
* @param {string} declarationName the name of a concept or enum
* @param {string} [propertyName] the name of a property (optional)
* @returns {*} the terms or null if it does not exist
*/
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;
return this.getTerms(property ? property.getNamespace() : namespace, locale, property ? property.getParent().getName() : declarationName, propertyName);
}

/**
Expand All @@ -195,28 +214,59 @@ class VocabularyManager {
* @param {string} locale the BCP-47 locale identifier
* @param {string} declarationName the name of a concept or enum
* @param {string} [propertyName] the name of a property (optional)
* @param {string} [identifier] the identifier of the term (optional)
* @returns {string} the term or null if it does not exist
*/
getTerm(namespace, locale, declarationName, propertyName) {
getTerm(namespace, locale, declarationName, propertyName, identifier) {
const voc = this.getVocabulary(namespace, locale);
let term = null;
if (voc) {
term = voc.getTerm(declarationName, propertyName);
term = voc.getTerm(declarationName, propertyName, identifier);
}
if (term) {
return term;
}
else {
const dashIndex = locale.lastIndexOf('-');
if (dashIndex >= 0) {
return this.getTerm(namespace, locale.substring(0, dashIndex), declarationName, propertyName);
return this.getTerm(namespace, locale.substring(0, dashIndex), declarationName, propertyName, identifier);
}
else {
return this.missingTermGenerator ? this.missingTermGenerator(namespace, locale, declarationName, propertyName) : null;
}
}
}

/**
* Gets the term for a concept, enum or property, looking up terms
* from a more general vocabulary if required
* @param {string} namespace the namespace
* @param {string} locale the BCP-47 locale identifier
* @param {string} declarationName the name of a concept or enum
* @param {string} [propertyName] the name of a property (optional)
* @returns {*} the terms or null if it does not exist
*/
getTerms(namespace, locale, declarationName, propertyName) {
const voc = this.getVocabulary(namespace, locale);
let term = null;
if (voc) {
term = voc.getElementTerms(declarationName, propertyName);
}
if (term) {
return term;
}
else {
const dashIndex = locale.lastIndexOf('-');
if (dashIndex >= 0) {
return this.getTerms(namespace, locale.substring(0, dashIndex), declarationName, propertyName);
}
else {
const missingKey = propertyName ? propertyName : declarationName;
return this.missingTermGenerator ? { [missingKey]: this.missingTermGenerator(namespace, locale, declarationName, propertyName) } : null;
}
}
}

/**
* Creates a DecoractorCommandSet with @Term decorators
* to decorate all model elements based on the vocabulary for a locale.
Expand All @@ -236,51 +286,101 @@ class VocabularyManager {

modelManager.getModelFiles().forEach(model => {
model.getAllDeclarations().forEach(decl => {
const term = this.resolveTerm(modelManager, model.getNamespace(), locale, decl.getName());
if (term) {
decoratorCommandSet.commands.push({
'$class': 'org.accordproject.decoratorcommands.Command',
'type': 'UPSERT',
'target': {
'$class': 'org.accordproject.decoratorcommands.CommandTarget',
'namespace': model.getNamespace(),
'declaration': decl.getName(),
},
'decorator': {
'$class': `${MetaModelNamespace}.Decorator`,
'name': 'Term',
'arguments': [
{
'$class': `${MetaModelNamespace}.DecoratorString`,
'value': term
const terms = this.resolveTerms(modelManager, model.getNamespace(), locale, decl.getName());
if (terms) {
Object.keys(terms).forEach( term => {
if(term === decl.getName()) {
decoratorCommandSet.commands.push({
'$class': 'org.accordproject.decoratorcommands.Command',
'type': 'UPSERT',
'target': {
'$class': 'org.accordproject.decoratorcommands.CommandTarget',
'namespace': model.getNamespace(),
'declaration': decl.getName(),
},
]
'decorator': {
'$class': `${MetaModelNamespace}.Decorator`,
'name': 'Term',
'arguments': [
{
'$class': `${MetaModelNamespace}.DecoratorString`,
'value': terms[term]
},
]
}
});
}
else if(term.localeCompare('properties')) {
decoratorCommandSet.commands.push({
'$class': 'org.accordproject.decoratorcommands.Command',
'type': 'UPSERT',
'target': {
'$class': 'org.accordproject.decoratorcommands.CommandTarget',
'namespace': model.getNamespace(),
'declaration': decl.getName(),
},
'decorator': {
'$class': `${MetaModelNamespace}.Decorator`,
'name': `Term_${term}`,
'arguments': [
{
'$class': `${MetaModelNamespace}.DecoratorString`,
'value': terms[term]
},
]
}
});
}
});
}

decl.getProperties?.().forEach(property => {
const propertyTerm = this.resolveTerm(modelManager, model.getNamespace(), locale, decl.getName(), property.getName());

if (propertyTerm) {
decoratorCommandSet.commands.push({
'$class': 'org.accordproject.decoratorcommands.Command',
'type': 'UPSERT',
'target': {
'$class': 'org.accordproject.decoratorcommands.CommandTarget',
'namespace': model.getNamespace(),
'declaration': decl.getName(),
'property': property.getName()
},
'decorator': {
'$class': `${MetaModelNamespace}.Decorator`,
'name': 'Term',
'arguments': [
{
'$class': `${MetaModelNamespace}.DecoratorString`,
'value': propertyTerm
const propertyTerms = this.resolveTerms(modelManager, model.getNamespace(), locale, decl.getName(), property.getName());
if (propertyTerms) {
Object.keys(propertyTerms).forEach( term => {
if(term === property.getName()) {
decoratorCommandSet.commands.push({
'$class': 'org.accordproject.decoratorcommands.Command',
'type': 'UPSERT',
'target': {
'$class': 'org.accordproject.decoratorcommands.CommandTarget',
'namespace': model.getNamespace(),
'declaration': decl.getName(),
'property': property.getName()
},
'decorator': {
'$class': `${MetaModelNamespace}.Decorator`,
'name': 'Term',
'arguments': [
{
'$class': `${MetaModelNamespace}.DecoratorString`,
'value': propertyTerms[term]
},
]
}
});
}
else {
decoratorCommandSet.commands.push({
'$class': 'org.accordproject.decoratorcommands.Command',
'type': 'UPSERT',
'target': {
'$class': 'org.accordproject.decoratorcommands.CommandTarget',
'namespace': model.getNamespace(),
'declaration': decl.getName(),
'property': property.getName()
},
]
'decorator': {
'$class': `${MetaModelNamespace}.Decorator`,
'name': `Term_${term}`,
'arguments': [
{
'$class': `${MetaModelNamespace}.DecoratorString`,
'value': propertyTerms[term]
},
]
}
});
}
});
}
Expand Down
Loading

0 comments on commit ac70543

Please sign in to comment.