-
-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(core) Add utility for loading a model manager
Signed-off-by: Jerome Simeon <jeromesimeon@me.com>
- Loading branch information
1 parent
8eec864
commit 999fa14
Showing
7 changed files
with
219 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
'use strict'; | ||
|
||
const fs = require('fs'); | ||
|
||
const DefaultModelFileLoader = require('./introspect/loaders/defaultmodelfileloader'); | ||
const ModelFile = require('./introspect/modelfile'); | ||
const ModelManager = require('./modelmanager'); | ||
|
||
const defaultSystemContent = `namespace org.accordproject.base | ||
abstract asset Asset { } | ||
abstract participant Participant { } | ||
abstract transaction Transaction identified by transactionId { | ||
o String transactionId | ||
} | ||
abstract event Event identified by eventId { | ||
o String eventId | ||
}`; | ||
const defaultSystemName = '@org.accordproject.base'; | ||
|
||
/** | ||
* Create a ModelManager from model files, with an optional system model. | ||
* | ||
* If a ctoFile is not provided, the Accord Project system model is used. | ||
* | ||
* @class | ||
* @memberof module:concerto-core | ||
*/ | ||
class ModelLoader { | ||
/** | ||
* Add model file | ||
* | ||
* @param {object} modelFileLoader - the model loader | ||
* @param {object} modelManager - the model manager | ||
* @param {string} ctoFile - the model file | ||
* @param {boolean} system - whether this is a system model | ||
* @return {object} the model manager | ||
* @private | ||
*/ | ||
static async addModel(modelFileLoader, modelManager, ctoFile, system) { | ||
let modelFile = null; | ||
if (system && !ctoFile) { | ||
modelFile = new ModelFile(modelManager, defaultSystemContent, defaultSystemName, true); | ||
} else if(modelFileLoader.accepts(ctoFile)) { | ||
modelFile = await modelFileLoader.load(ctoFile); | ||
} else { | ||
const content = fs.readFileSync(ctoFile, 'utf8'); | ||
modelFile = new ModelFile(modelManager, content, ctoFile); | ||
} | ||
|
||
if (system) { | ||
modelManager.addModelFile(modelFile, modelFile.getName(), false, true); | ||
} else { | ||
modelManager.addModelFile(modelFile, modelFile.getName(), true, false); | ||
} | ||
|
||
return modelManager; | ||
} | ||
|
||
/** | ||
* Load system and models in a new model manager | ||
* | ||
* @param {string} ctoSystemFile - the system model file | ||
* @param {string[]} ctoFiles - the CTO files (can be local file paths or URLs) | ||
* @return {object} the model manager | ||
*/ | ||
static async loadModelManager(ctoSystemFile, ctoFiles) { | ||
let modelManager = new ModelManager(); | ||
const modelFileLoader = new DefaultModelFileLoader(modelManager); | ||
|
||
// Load system model | ||
modelManager = await ModelLoader.addModel(modelFileLoader,modelManager,ctoSystemFile,true); | ||
|
||
// Load user models | ||
for( let ctoFile of ctoFiles ) { | ||
modelManager = await ModelLoader.addModel(modelFileLoader,modelManager,ctoFile,false); | ||
} | ||
|
||
// Validate update models | ||
await modelManager.updateExternalModels(); | ||
return modelManager; | ||
} | ||
|
||
} | ||
|
||
module.exports = ModelLoader; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
'use strict'; | ||
|
||
const Factory = require('../lib/factory'); | ||
const ModelLoader = require('../lib/modelloader'); | ||
const ModelManager = require('../lib/modelmanager'); | ||
const TypeNotFoundException = require('../lib/typenotfoundexception'); | ||
const Serializer = require('../lib/serializer'); | ||
|
||
const chai = require('chai'); | ||
chai.use(require('chai-things')); | ||
chai.use(require('chai-as-promised')); | ||
|
||
describe('ModelLoader', () => { | ||
|
||
let modelBase = './test/data/model/model-base.cto'; | ||
let modelUrl = 'https://models.accordproject.org/patents/patent.cto'; | ||
|
||
beforeEach(() => { | ||
}); | ||
|
||
afterEach(() => { | ||
}); | ||
|
||
describe('#loadModelFromFile', function() { | ||
it('should load models', async function() { | ||
const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); | ||
(function() { | ||
modelManager.getType('String'); | ||
}).should.throw(TypeNotFoundException); | ||
}); | ||
|
||
it('should throw an error for a namespace that does not exist', async function() { | ||
const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); | ||
(function() { | ||
modelManager.getType('org.acme.nosuchns.SimpleAsset'); | ||
}).should.throw(TypeNotFoundException, /org.acme.nosuchns/); | ||
}); | ||
|
||
it('should throw an error for an empty namespace', async function() { | ||
const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); | ||
(function() { | ||
modelManager.getType('NoSuchAsset'); | ||
}).should.throw(TypeNotFoundException, /NoSuchAsset/); | ||
}); | ||
|
||
it('should throw an error for a type that does not exist', async function() { | ||
const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); | ||
(function() { | ||
modelManager.getType('org.acme.base.NoSuchAsset'); | ||
}).should.throw(TypeNotFoundException, /NoSuchAsset/); | ||
}); | ||
|
||
it('should return the class declaration for a valid type', async function() { | ||
const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); | ||
const declaration = modelManager.getType('org.acme.base.AbstractAsset'); | ||
declaration.getFullyQualifiedName().should.equal('org.acme.base.AbstractAsset'); | ||
}); | ||
}); | ||
|
||
describe('#loadModelFromUrl', function() { | ||
it('should load models', async function() { | ||
const modelManager = await ModelLoader.loadModelManager(null, [modelUrl]); | ||
(modelManager instanceof ModelManager).should.be.true; | ||
}); | ||
}); | ||
|
||
describe('#getFactory', () => { | ||
|
||
it('should return a factory', async () => { | ||
const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); | ||
modelManager.getFactory().should.be.an.instanceOf(Factory); | ||
}); | ||
|
||
}); | ||
|
||
describe('#getSerializer', () => { | ||
|
||
it('should return a serializer', async () => { | ||
const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); | ||
modelManager.getSerializer().should.be.an.instanceOf(Serializer); | ||
}); | ||
|
||
}); | ||
|
||
describe('#hasInstance', () => { | ||
it('should return true for a valid ModelManager', async () => { | ||
const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); | ||
(modelManager instanceof ModelManager).should.be.true; | ||
}); | ||
}); | ||
|
||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters