From a8860fbeb1f9e7ef398053631decc6eab6c3460c Mon Sep 17 00:00:00 2001 From: Jonathan Casey Date: Mon, 2 Oct 2023 22:26:25 +0100 Subject: [PATCH] fix merge conflicts Signed-off-by: Jonathan Casey --- .../concerto-core/lib/decoratormanager.js | 3 +- .../invalid-target-element.json | 21 ++++ .../decoratorcommands/map-declaration.json | 112 +++++++++++++++++ .../test/data/decoratorcommands/test.cto | 11 ++ .../concerto-core/test/decoratormanager.js | 115 ++++++++++++++++++ 5 files changed, 260 insertions(+), 2 deletions(-) create mode 100644 packages/concerto-core/test/data/decoratorcommands/invalid-target-element.json create mode 100644 packages/concerto-core/test/data/decoratorcommands/map-declaration.json diff --git a/packages/concerto-core/lib/decoratormanager.js b/packages/concerto-core/lib/decoratormanager.js index 3a07b923e..8c51835bd 100644 --- a/packages/concerto-core/lib/decoratormanager.js +++ b/packages/concerto-core/lib/decoratormanager.js @@ -337,9 +337,8 @@ class DecoratorManager { break; default: - throw new Error('Unrecognised Element value found: ' + target.element ); + throw new Error('Decorator Command contains invalid target element: ' + target.element ); } - } else if (target.type) { if (this.falsyOrEqual(target.type, declaration.key.$class)) { this.applyDecorator(declaration.key, type, decorator); diff --git a/packages/concerto-core/test/data/decoratorcommands/invalid-target-element.json b/packages/concerto-core/test/data/decoratorcommands/invalid-target-element.json new file mode 100644 index 000000000..d111c3767 --- /dev/null +++ b/packages/concerto-core/test/data/decoratorcommands/invalid-target-element.json @@ -0,0 +1,21 @@ +{ + "$class" : "org.accordproject.decoratorcommands@0.3.0.DecoratorCommandSet", + "name" : "invalid-target-element", + "version": "1.0.0", + "commands" : [ + { + "$class" : "org.accordproject.decoratorcommands@0.3.0.Command", + "type" : "UPSERT", + "target" : { + "$class" : "org.accordproject.decoratorcommands@0.3.0.CommandTarget", + "namespace" : "test@1.0.0", + "declaration" : "Dictionary", + "element" : "INVALID_ELEMENT" + }, + "decorator" : { + "$class" : "concerto.metamodel@1.0.0.Decorator", + "name" : "Test" + } + } + ] +} diff --git a/packages/concerto-core/test/data/decoratorcommands/map-declaration.json b/packages/concerto-core/test/data/decoratorcommands/map-declaration.json new file mode 100644 index 000000000..3aaed22c6 --- /dev/null +++ b/packages/concerto-core/test/data/decoratorcommands/map-declaration.json @@ -0,0 +1,112 @@ +{ + "$class" : "org.accordproject.decoratorcommands@0.3.0.DecoratorCommandSet", + "name" : "web", + "version": "1.0.0", + "commands" : [ + { + "$class" : "org.accordproject.decoratorcommands@0.3.0.Command", + "type" : "UPSERT", + "target" : { + "$class" : "org.accordproject.decoratorcommands@0.3.0.CommandTarget", + "namespace" : "test@1.0.0", + "declaration" : "Dictionary", + "type" : "concerto.metamodel@1.0.0.StringMapKeyType", + "element": "KEY" + }, + "decorator" : { + "$class" : "concerto.metamodel@1.0.0.Decorator", + "name" : "Foo", + "arguments" : [] + } + }, + { + "$class" : "org.accordproject.decoratorcommands@0.3.0.Command", + "type" : "UPSERT", + "target" : { + "$class" : "org.accordproject.decoratorcommands@0.3.0.CommandTarget", + "namespace" : "test@1.0.0", + "declaration" : "Dictionary", + "type" : "concerto.metamodel@1.0.0.StringMapValueType", + "element": "VALUE" + }, + "decorator" : { + "$class" : "concerto.metamodel@1.0.0.Decorator", + "name" : "Bar", + "arguments" : [] + } + }, + { + "$class" : "org.accordproject.decoratorcommands@0.3.0.Command", + "type" : "UPSERT", + "target" : { + "$class" : "org.accordproject.decoratorcommands@0.3.0.CommandTarget", + "namespace" : "test@1.0.0", + "declaration" : "Dictionary", + "element": "*" + }, + "decorator" : { + "$class" : "concerto.metamodel@1.0.0.Decorator", + "name" : "Baz", + "arguments" : [] + } + }, + { + "$class" : "org.accordproject.decoratorcommands@0.3.0.Command", + "type" : "UPSERT", + "target" : { + "$class" : "org.accordproject.decoratorcommands@0.3.0.CommandTarget", + "namespace" : "test@1.0.0", + "declaration" : "Dictionary", + "type" : "concerto.metamodel@1.0.0.StringMapKeyType" + }, + "decorator" : { + "$class" : "concerto.metamodel@1.0.0.Decorator", + "name" : "DecoratesKeyByType", + "arguments" : [] + } + }, + { + "$class" : "org.accordproject.decoratorcommands@0.3.0.Command", + "type" : "UPSERT", + "target" : { + "$class" : "org.accordproject.decoratorcommands@0.3.0.CommandTarget", + "namespace" : "test@1.0.0", + "declaration" : "Dictionary", + "type" : "concerto.metamodel@1.0.0.StringMapValueType" + }, + "decorator" : { + "$class" : "concerto.metamodel@1.0.0.Decorator", + "name" : "DecoratesValueByType", + "arguments" : [] + } + }, + { + "$class" : "org.accordproject.decoratorcommands@0.3.0.Command", + "type" : "UPSERT", + "target" : { + "$class" : "org.accordproject.decoratorcommands@0.3.0.CommandTarget", + "namespace" : "test@1.0.0", + "type" : "concerto.metamodel@1.0.0.StringMapKeyType" + }, + "decorator" : { + "$class" : "concerto.metamodel@1.0.0.Decorator", + "name" : "DecoratesAllMapKeys", + "arguments" : [] + } + }, + { + "$class" : "org.accordproject.decoratorcommands@0.3.0.Command", + "type" : "UPSERT", + "target" : { + "$class" : "org.accordproject.decoratorcommands@0.3.0.CommandTarget", + "namespace" : "test@1.0.0", + "type" : "concerto.metamodel@1.0.0.StringMapValueType" + }, + "decorator" : { + "$class" : "concerto.metamodel@1.0.0.Decorator", + "name" : "DecoratesAllMapValues", + "arguments" : [] + } + } + ] +} diff --git a/packages/concerto-core/test/data/decoratorcommands/test.cto b/packages/concerto-core/test/data/decoratorcommands/test.cto index 1595a6c50..abfd024f5 100644 --- a/packages/concerto-core/test/data/decoratorcommands/test.cto +++ b/packages/concerto-core/test/data/decoratorcommands/test.cto @@ -12,4 +12,15 @@ concept Person { o String address1 o String address2 o Integer zip + o Dictionary dictionary +} + +map Dictionary { + o String + o String +} + +map Rolodex { + o String + o String } \ No newline at end of file diff --git a/packages/concerto-core/test/decoratormanager.js b/packages/concerto-core/test/decoratormanager.js index ac31e6c41..ecda86163 100644 --- a/packages/concerto-core/test/decoratormanager.js +++ b/packages/concerto-core/test/decoratormanager.js @@ -145,6 +145,107 @@ describe('DecoratorManager', () => { (decoratorZipProperty ===null).should.be.true; }); + it('should decorate the specified element on the specified Map Declaration (Map Key)', async function() { + // load a model to decorate + const testModelManager = new ModelManager({strict:true, skipLocationNodes: true}); + const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8'); + testModelManager.addCTOModel(modelText, 'test.cto'); + + const dcs = fs.readFileSync('./test/data/decoratorcommands/map-declaration.json', 'utf-8'); + const decoratedModelManager = DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs), + {validate: true, validateCommands: true}); + + const dictionary = decoratedModelManager.getType('test@1.0.0.Dictionary'); + dictionary.should.not.be.null; + dictionary.key.getDecorator('Foo').should.not.be.null; + }); + + it('should decorate the specified type on the specified Map Declaration (Map Key)', async function() { + // load a model to decorate + const testModelManager = new ModelManager({strict:true, skipLocationNodes: true}); + const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8'); + testModelManager.addCTOModel(modelText, 'test.cto'); + + const dcs = fs.readFileSync('./test/data/decoratorcommands/map-declaration.json', 'utf-8'); + const decoratedModelManager = DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs), + {validate: true, validateCommands: true}); + + const dictionary = decoratedModelManager.getType('test@1.0.0.Dictionary'); + dictionary.should.not.be.null; + dictionary.key.getDecorator('DecoratesKeyByType').should.not.be.null; + }); + + it('should decorate the specified element on the specified Map Declaration (Map Value)', async function() { + // load a model to decorate + const testModelManager = new ModelManager({strict:true, skipLocationNodes: true}); + const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8'); + testModelManager.addCTOModel(modelText, 'test.cto'); + + const dcs = fs.readFileSync('./test/data/decoratorcommands/map-declaration.json', 'utf-8'); + const decoratedModelManager = DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs), + {validate: true, validateCommands: true}); + + const dictionary = decoratedModelManager.getType('test@1.0.0.Dictionary'); + + dictionary.should.not.be.null; + dictionary.value.getDecorator('Bar').should.not.be.null; + }); + + it('should decorate the specified type on the specified Map Declaration (Map Value)', async function() { + // load a model to decorate + const testModelManager = new ModelManager({strict:true, skipLocationNodes: true}); + const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8'); + testModelManager.addCTOModel(modelText, 'test.cto'); + + const dcs = fs.readFileSync('./test/data/decoratorcommands/map-declaration.json', 'utf-8'); + const decoratedModelManager = DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs), + {validate: true, validateCommands: true}); + + const dictionary = decoratedModelManager.getType('test@1.0.0.Dictionary'); + dictionary.should.not.be.null; + dictionary.value.getDecorator('DecoratesValueByType').should.not.be.null; + }); + + it('should decorate both Key and Value elements on the specified Map Declaration', async function() { + // load a model to decorate + const testModelManager = new ModelManager({strict:true, skipLocationNodes: true}); + const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8'); + testModelManager.addCTOModel(modelText, 'test.cto'); + + const dcs = fs.readFileSync('./test/data/decoratorcommands/map-declaration.json', 'utf-8'); + const decoratedModelManager = DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs), + {validate: true, validateCommands: true}); + + const dictionary = decoratedModelManager.getType('test@1.0.0.Dictionary'); + + dictionary.should.not.be.null; + dictionary.key.getDecorator('Baz').should.not.be.null; + dictionary.value.getDecorator('Baz').should.not.be.null; + }); + + it('should decorate all Map Declaration Key and Value elements on the model when a declaration is not specified', async function() { + // load a model to decorate + const testModelManager = new ModelManager({strict:true, skipLocationNodes: true}); + const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8'); + testModelManager.addCTOModel(modelText, 'test.cto'); + + const dcs = fs.readFileSync('./test/data/decoratorcommands/map-declaration.json', 'utf-8'); + const decoratedModelManager = DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs), + {validate: true, validateCommands: true}); + + + const dictionary = decoratedModelManager.getType('test@1.0.0.Dictionary'); + const rolodex = decoratedModelManager.getType('test@1.0.0.Rolodex'); + + dictionary.should.not.be.null; + dictionary.key.getDecorator('DecoratesAllMapKeys').should.not.be.null; + dictionary.value.getDecorator('DecoratesAllMapValues').should.not.be.null; + + rolodex.should.not.be.null; + rolodex.key.getDecorator('DecoratesAllMapKeys').should.not.be.null; + rolodex.value.getDecorator('DecoratesAllMapValues').should.not.be.null; + }); + it('should fail with invalid command', async function() { // load a model to decorate const testModelManager = new ModelManager({strict:true}); @@ -243,6 +344,20 @@ describe('DecoratorManager', () => { {validate: true, validateCommands: true}); }).should.throw(/Decorator Command references both property and properties. You must either reference a single property or a list of properites./); }); + + it('should detect invalid target element', async function() { + // load a model to decorate + const testModelManager = new ModelManager({strict:true}); + const modelText = fs.readFileSync('./test/data/decoratorcommands/test.cto', 'utf-8'); + testModelManager.addCTOModel(modelText, 'test.cto'); + + const dcs = fs.readFileSync('./test/data/decoratorcommands/invalid-target-element.json', 'utf-8'); + + (() => { + DecoratorManager.decorateModels( testModelManager, JSON.parse(dcs), + {validate: true, validateCommands: true}); + }).should.throw(/Decorator Command contains invalid target element: INVALID_ELEMENT/); + }); }); describe('#validate', function() {