@@ -179,13 +179,32 @@ class VocabularyManager {
179179 * @param {string } locale the BCP-47 locale identifier
180180 * @param {string } declarationName the name of a concept or enum
181181 * @param {string } [propertyName] the name of a property (optional)
182+ * @param {string } [identifier] the identifier of the term (optional)
182183 * @returns {string } the term or null if it does not exist
183184 */
184- resolveTerm ( modelManager , namespace , locale , declarationName , propertyName ) {
185+ resolveTerm ( modelManager , namespace , locale , declarationName , propertyName , identifier ) {
185186 const modelFile = modelManager . getModelFile ( namespace ) ;
186187 const classDecl = modelFile ? modelFile . getType ( declarationName ) : null ;
187188 const property = propertyName ? classDecl ? classDecl . getProperty ( propertyName ) : null : null ;
188- return this . getTerm ( property ? property . getNamespace ( ) : namespace , locale , property ? property . getParent ( ) . getName ( ) : declarationName , propertyName ) ;
189+ return this . getTerm ( property ? property . getNamespace ( ) : namespace , locale , property ? property . getParent ( ) . getName ( ) : declarationName , propertyName , identifier ) ;
190+ }
191+
192+ /**
193+ * Resolve the terms for a property, looking up terms from a more general vocabulary
194+ * if required, and resolving properties using an object manager, allowing terms defined
195+ * on super types to be automatically resolved.
196+ * @param {ModelManager } modelManager the model manager
197+ * @param {string } namespace the namespace
198+ * @param {string } locale the BCP-47 locale identifier
199+ * @param {string } declarationName the name of a concept or enum
200+ * @param {string } [propertyName] the name of a property (optional)
201+ * @returns {* } the terms or null if it does not exist
202+ */
203+ resolveTerms ( modelManager , namespace , locale , declarationName , propertyName ) {
204+ const modelFile = modelManager . getModelFile ( namespace ) ;
205+ const classDecl = modelFile ? modelFile . getType ( declarationName ) : null ;
206+ const property = propertyName ? classDecl ? classDecl . getProperty ( propertyName ) : null : null ;
207+ return this . getTerms ( property ? property . getNamespace ( ) : namespace , locale , property ? property . getParent ( ) . getName ( ) : declarationName , propertyName ) ;
189208 }
190209
191210 /**
@@ -195,28 +214,59 @@ class VocabularyManager {
195214 * @param {string } locale the BCP-47 locale identifier
196215 * @param {string } declarationName the name of a concept or enum
197216 * @param {string } [propertyName] the name of a property (optional)
217+ * @param {string } [identifier] the identifier of the term (optional)
198218 * @returns {string } the term or null if it does not exist
199219 */
200- getTerm ( namespace , locale , declarationName , propertyName ) {
220+ getTerm ( namespace , locale , declarationName , propertyName , identifier ) {
201221 const voc = this . getVocabulary ( namespace , locale ) ;
202222 let term = null ;
203223 if ( voc ) {
204- term = voc . getTerm ( declarationName , propertyName ) ;
224+ term = voc . getTerm ( declarationName , propertyName , identifier ) ;
205225 }
206226 if ( term ) {
207227 return term ;
208228 }
209229 else {
210230 const dashIndex = locale . lastIndexOf ( '-' ) ;
211231 if ( dashIndex >= 0 ) {
212- return this . getTerm ( namespace , locale . substring ( 0 , dashIndex ) , declarationName , propertyName ) ;
232+ return this . getTerm ( namespace , locale . substring ( 0 , dashIndex ) , declarationName , propertyName , identifier ) ;
213233 }
214234 else {
215235 return this . missingTermGenerator ? this . missingTermGenerator ( namespace , locale , declarationName , propertyName ) : null ;
216236 }
217237 }
218238 }
219239
240+ /**
241+ * Gets the term for a concept, enum or property, looking up terms
242+ * from a more general vocabulary if required
243+ * @param {string } namespace the namespace
244+ * @param {string } locale the BCP-47 locale identifier
245+ * @param {string } declarationName the name of a concept or enum
246+ * @param {string } [propertyName] the name of a property (optional)
247+ * @returns {* } the terms or null if it does not exist
248+ */
249+ getTerms ( namespace , locale , declarationName , propertyName ) {
250+ const voc = this . getVocabulary ( namespace , locale ) ;
251+ let term = null ;
252+ if ( voc ) {
253+ term = voc . getElementTerms ( declarationName , propertyName ) ;
254+ }
255+ if ( term ) {
256+ return term ;
257+ }
258+ else {
259+ const dashIndex = locale . lastIndexOf ( '-' ) ;
260+ if ( dashIndex >= 0 ) {
261+ return this . getTerms ( namespace , locale . substring ( 0 , dashIndex ) , declarationName , propertyName ) ;
262+ }
263+ else {
264+ const missingKey = propertyName ? propertyName : declarationName ;
265+ return this . missingTermGenerator ? { [ missingKey ] : this . missingTermGenerator ( namespace , locale , declarationName , propertyName ) } : null ;
266+ }
267+ }
268+ }
269+
220270 /**
221271 * Creates a DecoractorCommandSet with @Term decorators
222272 * to decorate all model elements based on the vocabulary for a locale.
@@ -236,51 +286,101 @@ class VocabularyManager {
236286
237287 modelManager . getModelFiles ( ) . forEach ( model => {
238288 model . getAllDeclarations ( ) . forEach ( decl => {
239- const term = this . resolveTerm ( modelManager , model . getNamespace ( ) , locale , decl . getName ( ) ) ;
240- if ( term ) {
241- decoratorCommandSet . commands . push ( {
242- '$class' : 'org.accordproject.decoratorcommands.Command' ,
243- 'type' : 'UPSERT' ,
244- 'target' : {
245- '$class' : 'org.accordproject.decoratorcommands.CommandTarget' ,
246- 'namespace' : model . getNamespace ( ) ,
247- 'declaration' : decl . getName ( ) ,
248- } ,
249- 'decorator' : {
250- '$class' : `${ MetaModelNamespace } .Decorator` ,
251- 'name' : 'Term' ,
252- 'arguments' : [
253- {
254- '$class' : `${ MetaModelNamespace } .DecoratorString` ,
255- 'value' : term
289+ const terms = this . resolveTerms ( modelManager , model . getNamespace ( ) , locale , decl . getName ( ) ) ;
290+ if ( terms ) {
291+ Object . keys ( terms ) . forEach ( term => {
292+ if ( term === decl . getName ( ) ) {
293+ decoratorCommandSet . commands . push ( {
294+ '$class' : 'org.accordproject.decoratorcommands.Command' ,
295+ 'type' : 'UPSERT' ,
296+ 'target' : {
297+ '$class' : 'org.accordproject.decoratorcommands.CommandTarget' ,
298+ 'namespace' : model . getNamespace ( ) ,
299+ 'declaration' : decl . getName ( ) ,
256300 } ,
257- ]
301+ 'decorator' : {
302+ '$class' : `${ MetaModelNamespace } .Decorator` ,
303+ 'name' : 'Term' ,
304+ 'arguments' : [
305+ {
306+ '$class' : `${ MetaModelNamespace } .DecoratorString` ,
307+ 'value' : terms [ term ]
308+ } ,
309+ ]
310+ }
311+ } ) ;
312+ }
313+ else if ( term . localeCompare ( 'properties' ) ) {
314+ decoratorCommandSet . commands . push ( {
315+ '$class' : 'org.accordproject.decoratorcommands.Command' ,
316+ 'type' : 'UPSERT' ,
317+ 'target' : {
318+ '$class' : 'org.accordproject.decoratorcommands.CommandTarget' ,
319+ 'namespace' : model . getNamespace ( ) ,
320+ 'declaration' : decl . getName ( ) ,
321+ } ,
322+ 'decorator' : {
323+ '$class' : `${ MetaModelNamespace } .Decorator` ,
324+ 'name' : `Term_${ term } ` ,
325+ 'arguments' : [
326+ {
327+ '$class' : `${ MetaModelNamespace } .DecoratorString` ,
328+ 'value' : terms [ term ]
329+ } ,
330+ ]
331+ }
332+ } ) ;
258333 }
259334 } ) ;
260335 }
261336
262337 decl . getProperties ?. ( ) . forEach ( property => {
263- const propertyTerm = this . resolveTerm ( modelManager , model . getNamespace ( ) , locale , decl . getName ( ) , property . getName ( ) ) ;
264-
265- if ( propertyTerm ) {
266- decoratorCommandSet . commands . push ( {
267- '$class' : 'org.accordproject.decoratorcommands.Command' ,
268- 'type' : 'UPSERT' ,
269- 'target' : {
270- '$class' : 'org.accordproject.decoratorcommands.CommandTarget' ,
271- 'namespace' : model . getNamespace ( ) ,
272- 'declaration' : decl . getName ( ) ,
273- 'property' : property . getName ( )
274- } ,
275- 'decorator' : {
276- '$class' : `${ MetaModelNamespace } .Decorator` ,
277- 'name' : 'Term' ,
278- 'arguments' : [
279- {
280- '$class' : `${ MetaModelNamespace } .DecoratorString` ,
281- 'value' : propertyTerm
338+ const propertyTerms = this . resolveTerms ( modelManager , model . getNamespace ( ) , locale , decl . getName ( ) , property . getName ( ) ) ;
339+ if ( propertyTerms ) {
340+ Object . keys ( propertyTerms ) . forEach ( term => {
341+ if ( term === property . getName ( ) ) {
342+ decoratorCommandSet . commands . push ( {
343+ '$class' : 'org.accordproject.decoratorcommands.Command' ,
344+ 'type' : 'UPSERT' ,
345+ 'target' : {
346+ '$class' : 'org.accordproject.decoratorcommands.CommandTarget' ,
347+ 'namespace' : model . getNamespace ( ) ,
348+ 'declaration' : decl . getName ( ) ,
349+ 'property' : property . getName ( )
350+ } ,
351+ 'decorator' : {
352+ '$class' : `${ MetaModelNamespace } .Decorator` ,
353+ 'name' : 'Term' ,
354+ 'arguments' : [
355+ {
356+ '$class' : `${ MetaModelNamespace } .DecoratorString` ,
357+ 'value' : propertyTerms [ term ]
358+ } ,
359+ ]
360+ }
361+ } ) ;
362+ }
363+ else {
364+ decoratorCommandSet . commands . push ( {
365+ '$class' : 'org.accordproject.decoratorcommands.Command' ,
366+ 'type' : 'UPSERT' ,
367+ 'target' : {
368+ '$class' : 'org.accordproject.decoratorcommands.CommandTarget' ,
369+ 'namespace' : model . getNamespace ( ) ,
370+ 'declaration' : decl . getName ( ) ,
371+ 'property' : property . getName ( )
282372 } ,
283- ]
373+ 'decorator' : {
374+ '$class' : `${ MetaModelNamespace } .Decorator` ,
375+ 'name' : `Term_${ term } ` ,
376+ 'arguments' : [
377+ {
378+ '$class' : `${ MetaModelNamespace } .DecoratorString` ,
379+ 'value' : propertyTerms [ term ]
380+ } ,
381+ ]
382+ }
383+ } ) ;
284384 }
285385 } ) ;
286386 }
0 commit comments