Skip to content

Commit

Permalink
feat(decoratormanager) add validate method (accordproject#726)
Browse files Browse the repository at this point in the history
* feat(decoratormanager) add validate method

Signed-off-by: Ertugrul Karademir <[email protected]>
  • Loading branch information
dselman authored and ekarademir committed Oct 10, 2023
1 parent c637f19 commit 030f412
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 14 deletions.
1 change: 1 addition & 0 deletions packages/concerto-core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class Concerto {
}
+ object setCurrentTime()
class DecoratorManager {
+ ModelManager validate(decoratorCommandSet,ModelFile[]) throws Error
+ ModelManager decorateModels(ModelManager,decoratorCommandSet,object?,boolean?,boolean?)
+ void validateCommand(ModelManager,command)
+ Boolean falsyOrEqual(string||,string[])
Expand Down
3 changes: 2 additions & 1 deletion packages/concerto-core/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
# Note that the latest public API is documented using JSDocs and is available in api.txt.
#

Version 3.13.0 {a7060663ad5bb322ec4ee760baa7ab1a} 2023-10-01
Version 3.13.0 {125b7f97f8740628b2629b2793384cc7} 2023-10-03
- Update DecoratorManager to support multiple value compare
- Create DecoratorManager.validate method to validate structure of decorator command set

Version 3.12.4 {7738d5490ea8438677e1d21d704bb5aa} 2023-08-31
- Adds validate and validateCommands options to DecoratorManager.decorateModels
Expand Down
56 changes: 43 additions & 13 deletions packages/concerto-core/lib/decoratormanager.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ const Serializer = require('./serializer');
const Factory = require('./factory');
const ModelUtil = require('./modelutil');

// Types needed for TypeScript generation.
/* eslint-disable no-unused-vars */
/* istanbul ignore next */
if (global === undefined) {
const ModelFile = require('./introspect/modelfile');
}
/* eslint-enable no-unused-vars */


const DCS_MODEL = `concerto version "^3.0.0"
namespace [email protected]
Expand Down Expand Up @@ -105,6 +114,39 @@ function isUnversionedNamespaceEqual(modelFile, unversionedNamespace) {
* @memberof module:concerto-core
*/
class DecoratorManager {

/**
* Structural validation of the decoratorCommandSet against the
* Decorator Command Set model. Note that this only checks the
* structural integrity of the command set, it cannot check
* whether the commands are valid with respect to a model manager.
* Use the options.validateCommands option with decorateModels
* method to perform semantic validation.
* @param {*} decoratorCommandSet the DecoratorCommandSet object
* @param {ModelFile[]} [modelFiles] an optional array of model
* files that are added to the validation model manager returned
* @returns {ModelManager} the model manager created for validation
* @throws {Error} throws an error if the decoratorCommandSet is invalid
*/
static validate(decoratorCommandSet, modelFiles) {
const validationModelManager = new ModelManager({
strict: true,
metamodelValidation: true,
addMetamodel: true,
});
if(modelFiles) {
validationModelManager.addModelFiles(modelFiles);
}
validationModelManager.addCTOModel(
DCS_MODEL,
'[email protected]'
);
const factory = new Factory(validationModelManager);
const serializer = new Serializer(factory, validationModelManager);
serializer.fromJSON(decoratorCommandSet);
return validationModelManager;
}

/**
* Applies all the decorator commands from the DecoratorCommandSet
* to the ModelManager.
Expand All @@ -119,19 +161,7 @@ class DecoratorManager {
*/
static decorateModels(modelManager, decoratorCommandSet, options) {
if (options?.validate) {
const validationModelManager = new ModelManager({
strict: true,
metamodelValidation: true,
addMetamodel: true,
});
validationModelManager.addModelFiles(modelManager.getModelFiles());
validationModelManager.addCTOModel(
DCS_MODEL,
'[email protected]'
);
const factory = new Factory(validationModelManager);
const serializer = new Serializer(factory, validationModelManager);
serializer.fromJSON(decoratorCommandSet);
const validationModelManager = DecoratorManager.validate(decoratorCommandSet, modelManager.getModelFiles());
if (options?.validateCommands) {
decoratorCommandSet.commands.forEach((command) => {
DecoratorManager.validateCommand(
Expand Down
30 changes: 30 additions & 0 deletions packages/concerto-core/test/decoratormanager.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,36 @@ describe('DecoratorManager', () => {
});
});

describe('#validate', function() {
it('should support syntax validation', async function() {
const dcs = fs.readFileSync('./test/data/decoratorcommands/web.json', 'utf-8');
const validationModelManager = DecoratorManager.validate( JSON.parse(dcs));
validationModelManager.should.not.be.null;
});

it('should support syntax validation with model files', async function() {
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/web.json', 'utf-8');
const validationModelManager = DecoratorManager.validate(JSON.parse(dcs), testModelManager.getModelFiles());
validationModelManager.should.not.be.null;
validationModelManager.getType('[email protected]').should.not.be.null;
});

it('should fail syntax validation', async function() {
(() => {
DecoratorManager.validate( { $class: 'invalid' });
}).should.throw(/Namespace is not defined for type/);
});

it('should fail syntax validation', async function() {
(() => {
DecoratorManager.validate( { invalid: true });
}).should.throw(/Invalid JSON data/);
});
});

describe('#decorateModels', function() {
it('should support no validation', async function() {
const testModelManager = new ModelManager({strict:true});
Expand Down
15 changes: 15 additions & 0 deletions packages/concerto-core/types/lib/decoratormanager.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ export = DecoratorManager;
* @memberof module:concerto-core
*/
declare class DecoratorManager {
/**
* Structural validation of the decoratorCommandSet against the
* Decorator Command Set model. Note that this only checks the
* structural integrity of the command set, it cannot check
* whether the commands are valid with respect to a model manager.
* Use the options.validateCommands option with decorateModels
* method to perform semantic validation.
* @param {*} decoratorCommandSet the DecoratorCommandSet object
* @param {ModelFile[]} [modelFiles] an optional array of model
* files that are added to the validation model manager returned
* @returns {ModelManager} the model manager created for validation
* @throws {Error} throws an error if the decoratorCommandSet is invalid
*/
static validate(decoratorCommandSet: any, modelFiles?: ModelFile[]): ModelManager;
/**
* Applies all the decorator commands from the DecoratorCommandSet
* to the ModelManager.
Expand Down Expand Up @@ -61,4 +75,5 @@ declare class DecoratorManager {
*/
static executePropertyCommand(property: any, command: any): void;
}
import ModelFile = require("./introspect/modelfile");
import ModelManager = require("./modelmanager");

0 comments on commit 030f412

Please sign in to comment.