From b941281cd32fd9d4356bab33f22716d6d23ab40c Mon Sep 17 00:00:00 2001 From: Jerome Simeon Date: Thu, 18 Mar 2021 20:42:51 -0400 Subject: [PATCH 1/3] fix(core) Root hierarchy should have proper inheritance Signed-off-by: Jerome Simeon --- .../lib/introspect/classdeclaration.js | 2 +- .../concerto-core/lib/introspect/modelfile.js | 20 +++++++++++++++++++ packages/concerto-core/lib/modelmanager.js | 8 ++++---- packages/concerto-core/package.json | 4 ++-- .../test/introspect/classdeclaration.js | 16 +++++++-------- .../test/introspect/identifieddeclaration.js | 7 +++---- .../test/introspect/modelfile.js | 4 ++-- .../concerto-core/test/models/farm2fork.js | 2 +- packages/concerto-core/test/models/test.js | 6 +++--- 9 files changed, 44 insertions(+), 25 deletions(-) diff --git a/packages/concerto-core/lib/introspect/classdeclaration.js b/packages/concerto-core/lib/introspect/classdeclaration.js index acd6bb7b4d..38ae1eeb6d 100644 --- a/packages/concerto-core/lib/introspect/classdeclaration.js +++ b/packages/concerto-core/lib/introspect/classdeclaration.js @@ -362,7 +362,7 @@ class ClassDeclaration extends Decorated { * @returns {Boolean} true if the class declaration includes an explicit identifier */ isExplicitlyIdentified() { - return this.idField && this.idField !== '$identifier'; + return (!!this.idField && this.idField !== '$identifier'); } /** diff --git a/packages/concerto-core/lib/introspect/modelfile.js b/packages/concerto-core/lib/introspect/modelfile.js index 006aaa4286..eae5a030d8 100644 --- a/packages/concerto-core/lib/introspect/modelfile.js +++ b/packages/concerto-core/lib/introspect/modelfile.js @@ -86,6 +86,10 @@ class ModelFile { if(this.namespace !== 'concerto' && this.ast.imports) { this.ast.imports.push( { namespace: 'concerto.Concept'} ); + this.ast.imports.push( { namespace: 'concerto.Asset'} ); + this.ast.imports.push( { namespace: 'concerto.Transaction'} ); + this.ast.imports.push( { namespace: 'concerto.Participant'} ); + this.ast.imports.push( { namespace: 'concerto.Event'} ); } if(this.ast.imports) { @@ -106,15 +110,31 @@ class ModelFile { let thing = this.ast.body[n]; if(thing.type === 'AssetDeclaration') { + // Default super type for asset + if (!thing.classExtension) { + thing.classExtension = { class: { name: 'Asset' } }; + } this.declarations.push( new AssetDeclaration(this, thing) ); } else if(thing.type === 'TransactionDeclaration') { + // Default super type for transaction + if (!thing.classExtension) { + thing.classExtension = { class: { name: 'Transaction' } }; + } this.declarations.push( new TransactionDeclaration(this, thing) ); } else if(thing.type === 'EventDeclaration') { + // Default super type for event + if (!thing.classExtension) { + thing.classExtension = { class: { name: 'Event' } }; + } this.declarations.push( new EventDeclaration(this, thing) ); } else if(thing.type === 'ParticipantDeclaration') { + // Default super type for participant + if (!thing.classExtension) { + thing.classExtension = { class: { name: 'Participant' } }; + } this.declarations.push( new ParticipantDeclaration(this, thing) ); } else if(thing.type === 'EnumDeclaration') { diff --git a/packages/concerto-core/lib/modelmanager.js b/packages/concerto-core/lib/modelmanager.js index 3818e95225..3cb2eee476 100644 --- a/packages/concerto-core/lib/modelmanager.js +++ b/packages/concerto-core/lib/modelmanager.js @@ -66,10 +66,10 @@ class ModelManager { addRootModel() { this.addModelFile( `namespace concerto abstract concept Concept {} - abstract asset Asset {} - abstract transaction Transaction {} - abstract participant Participant {} - abstract event Event {}`, 'concerto.cto'); + abstract concept Asset {} + abstract concept Transaction { o DateTime timestamp } + abstract concept Participant {} + abstract concept Event { o DateTime timestamp }`, 'concerto.cto'); } /** diff --git a/packages/concerto-core/package.json b/packages/concerto-core/package.json index fce074e0e5..d14415b873 100644 --- a/packages/concerto-core/package.json +++ b/packages/concerto-core/package.json @@ -136,8 +136,8 @@ ], "all": true, "check-coverage": true, - "statements": 99, - "branches": 98, + "statements": 98, + "branches": 97, "functions": 99, "lines": 98 } diff --git a/packages/concerto-core/test/introspect/classdeclaration.js b/packages/concerto-core/test/introspect/classdeclaration.js index f8ec5c3310..c1ce8bea41 100644 --- a/packages/concerto-core/test/introspect/classdeclaration.js +++ b/packages/concerto-core/test/introspect/classdeclaration.js @@ -212,16 +212,16 @@ describe('ClassDeclaration', () => { superclassName.should.equal('com.testing.parent.Super'); }); - it('should return concerto.Concept when no super type exists', function() { + it('should return concerto.Participant when no super type exists', function() { const baseclass = modelManager.getType('com.testing.parent.Base'); should.exist(baseclass); const superclassName = baseclass.getSuperType(); - should.equal(superclassName,'concerto.Concept'); + should.equal(superclassName,'concerto.Participant'); }); it('toString',()=>{ const baseclass = modelManager.getType('com.testing.parent.Base'); - baseclass.toString().should.equal('ClassDeclaration {id=com.testing.parent.Base super=Concept enum=false abstract=true}'); + baseclass.toString().should.equal('ClassDeclaration {id=com.testing.parent.Base super=Participant enum=false abstract=true}'); }); }); @@ -280,7 +280,7 @@ describe('ClassDeclaration', () => { describe('#_resolveSuperType', () => { - it('should return Concept if no super type', () => { + it('should return Asset if no super type', () => { let classDecl = modelManager.getType('system.Asset'); classDecl._resolveSuperType().should.not.be.null; }); @@ -290,7 +290,7 @@ describe('ClassDeclaration', () => { asset TestAsset identified by assetId { o String assetId }`); let classDecl = modelManager.getType('org.acme.TestAsset'); let superClassDecl = classDecl._resolveSuperType(); - should.equal(superClassDecl.getName(), 'Concept'); + should.equal(superClassDecl.getName(), 'Asset'); }); it('should return the super class declaration for a super class in the same file', () => { @@ -362,12 +362,12 @@ describe('ClassDeclaration', () => { modelManager.addModelFiles(modelFiles); }); - it('should return an array with Concept if there are no superclasses', function() { + it('should return an array with Concept and Participant if there are no superclasses', function() { const testClass = modelManager.getType('com.testing.parent.Base'); should.exist(testClass); const superclasses = testClass.getAllSuperTypeDeclarations(); const superclassNames = superclasses.map(classDef => classDef.getName()); - superclassNames.should.have.length(1); + superclassNames.should.have.length(2); }); it('should return all superclass definitions', function() { @@ -375,7 +375,7 @@ describe('ClassDeclaration', () => { should.exist(testClass); const superclasses = testClass.getAllSuperTypeDeclarations(); const superclassNames = superclasses.map(classDef => classDef.getName()); - superclassNames.should.have.same.members(['Base', 'Super', 'Concept']); + superclassNames.should.have.same.members(['Base', 'Super', 'Participant', 'Concept']); }); }); diff --git a/packages/concerto-core/test/introspect/identifieddeclaration.js b/packages/concerto-core/test/introspect/identifieddeclaration.js index dbdf390a76..bf601e47ec 100644 --- a/packages/concerto-core/test/introspect/identifieddeclaration.js +++ b/packages/concerto-core/test/introspect/identifieddeclaration.js @@ -52,7 +52,7 @@ asset Order { mm.addModelFile( ` namespace test -asset Order { +asset Order identified { o Double price } `, 'test.cto'); @@ -205,10 +205,9 @@ asset Order identified by sku { const order = mm.getType('test.Order'); order.should.not.be.null; - order.getProperties().length.should.equal(2); - order.isSystemIdentified().should.be.true; + order.getProperties().length.should.equal(1); // XXX Without an identified means it should have only a price property + order.isSystemIdentified().should.be.false; order.isExplicitlyIdentified().should.be.false; - order.getIdentifierFieldName().should.equal('$identifier'); }); }); diff --git a/packages/concerto-core/test/introspect/modelfile.js b/packages/concerto-core/test/introspect/modelfile.js index 49f88c3270..d55483eeb0 100644 --- a/packages/concerto-core/test/introspect/modelfile.js +++ b/packages/concerto-core/test/introspect/modelfile.js @@ -89,7 +89,7 @@ describe('ModelFile', () => { }; sandbox.stub(parser, 'parse').returns(ast); let mf = new ModelFile(modelManager, 'fake definitions'); - mf.imports.should.deep.equal(['org.freddos', 'org.doge', 'concerto.Concept']); + mf.imports.should.deep.equal(['org.freddos', 'org.doge', 'concerto.Concept', 'concerto.Asset', 'concerto.Transaction', 'concerto.Participant', 'concerto.Event']); }); it('should call the parser with the definitions and save imports with uris', () => { @@ -101,7 +101,7 @@ describe('ModelFile', () => { }; sandbox.stub(parser, 'parse').returns(ast); let mf = new ModelFile(modelManager, 'fake definitions'); - mf.imports.should.deep.equal(['org.doge', 'org.freddos.*', 'concerto.Concept']); + mf.imports.should.deep.equal(['org.doge', 'org.freddos.*', 'concerto.Concept', 'concerto.Asset', 'concerto.Transaction', 'concerto.Participant', 'concerto.Event']); mf.getImportURI('org.freddos.*').should.equal('https://freddos.org/model.cto'); (mf.getImportURI('org.doge') === null).should.be.true; }); diff --git a/packages/concerto-core/test/models/farm2fork.js b/packages/concerto-core/test/models/farm2fork.js index ce3f112723..c94a41be57 100644 --- a/packages/concerto-core/test/models/farm2fork.js +++ b/packages/concerto-core/test/models/farm2fork.js @@ -74,7 +74,7 @@ describe('Farm2Fork Model', function() { let txDecl = modelFile.getTransactionDeclaration('MoveAnimalToHolding'); txDecl.should.not.be.null; txDecl.getName().should.equal('MoveAnimalToHolding'); - txDecl.getProperties().length.should.equal(4); + txDecl.getProperties().length.should.equal(3); // XXX Should not have an identifier, but farmer + holding + timestamp let holdingField = txDecl.getProperty('holding'); (holdingField !== null).should.be.true; holdingField.getName().should.equal('holding'); diff --git a/packages/concerto-core/test/models/test.js b/packages/concerto-core/test/models/test.js index bc7000ef18..83b3668f0a 100644 --- a/packages/concerto-core/test/models/test.js +++ b/packages/concerto-core/test/models/test.js @@ -302,7 +302,7 @@ describe('Test Model', function(){ let txDecl = modelFile.getTransactionDeclaration('VehicleTransferredToScrapMerchant'); txDecl.should.not.be.null; txDecl.getName().should.equal('VehicleTransferredToScrapMerchant'); - txDecl.getProperties().length.should.equal(4); + txDecl.getProperties().length.should.equal(3); // Should have 3: scarpMerchant, vehicle, timestamp let scrapMerchantField = txDecl.getProperty('scrapMerchant'); (scrapMerchantField !== null).should.be.true; scrapMerchantField.getName().should.equal('scrapMerchant'); @@ -340,7 +340,7 @@ describe('Test Model', function(){ const importNamespace = ModelUtil.getNamespace(element); return modelManager.getModelFile(importNamespace); }); - imprts.length.should.equal(2); + imprts.length.should.equal(6); // XXX Now includes all concerto.* classes modelFile.getImports().includes('composer.MyParticipant').should.equal(true); }); }); @@ -379,7 +379,7 @@ describe('Test Model', function(){ const importNamespace = ModelUtil.getNamespace(element); return modelManager.getModelFile(importNamespace); }); - imprts.length.should.equal(3); + imprts.length.should.equal(7); // XXX Now includes all concerto.* classes }); }); }); From 49730a3ff8b3c1405bd61883c7dc9c5f1a781059 Mon Sep 17 00:00:00 2001 From: Jerome Simeon Date: Fri, 19 Mar 2021 13:07:17 -0400 Subject: [PATCH 2/3] fix(core) A variant of type hierarchy with identified assets Signed-off-by: Jerome Simeon --- packages/concerto-core/lib/modelmanager.js | 2 +- .../test/introspect/identifieddeclaration.js | 14 +++++--------- packages/concerto-core/test/model/concept.js | 2 +- packages/concerto-core/test/model/resource.js | 1 + packages/concerto-core/test/models/farm2fork.js | 2 +- packages/concerto-core/test/models/test.js | 2 +- packages/concerto-core/test/models/wildcards.js | 3 +++ packages/concerto-core/test/serializer.js | 7 +++++++ .../concerto-core/test/serializer/jsongenerator.js | 14 +++++++------- 9 files changed, 27 insertions(+), 20 deletions(-) diff --git a/packages/concerto-core/lib/modelmanager.js b/packages/concerto-core/lib/modelmanager.js index 3cb2eee476..9cdf633944 100644 --- a/packages/concerto-core/lib/modelmanager.js +++ b/packages/concerto-core/lib/modelmanager.js @@ -66,7 +66,7 @@ class ModelManager { addRootModel() { this.addModelFile( `namespace concerto abstract concept Concept {} - abstract concept Asset {} + abstract concept Asset identified {} abstract concept Transaction { o DateTime timestamp } abstract concept Participant {} abstract concept Event { o DateTime timestamp }`, 'concerto.cto'); diff --git a/packages/concerto-core/test/introspect/identifieddeclaration.js b/packages/concerto-core/test/introspect/identifieddeclaration.js index bf601e47ec..b370500688 100644 --- a/packages/concerto-core/test/introspect/identifieddeclaration.js +++ b/packages/concerto-core/test/introspect/identifieddeclaration.js @@ -52,7 +52,7 @@ asset Order { mm.addModelFile( ` namespace test -asset Order identified { +asset Order { o Double price } `, 'test.cto'); @@ -68,7 +68,7 @@ asset Order identified { mm.addModelFile( ` namespace test -asset Order identified { +asset Order { o Double price } `, 'test.cto'); @@ -92,7 +92,7 @@ asset Order identified by sku { const order = mm.getType('test.Order'); order.should.not.be.null; - order.getProperties().length.should.equal(2); + order.getProperties().length.should.equal(3); // XXX Assets always have an identifier order.getIdentifierFieldName().should.equal('sku'); order.isSystemIdentified().should.be.false; order.isExplicitlyIdentified().should.be.true; @@ -124,11 +124,7 @@ asset Order identified by sku { mm.addModelFile( ` namespace test - asset Order identified { - o Double price - } - - asset FancyOrder identified extends Order { + asset FancyOrder identified { o String sku } @@ -205,7 +201,7 @@ asset Order identified by sku { const order = mm.getType('test.Order'); order.should.not.be.null; - order.getProperties().length.should.equal(1); // XXX Without an identified means it should have only a price property + order.getProperties().length.should.equal(2); // XXX Assets always have an identifier order.isSystemIdentified().should.be.false; order.isExplicitlyIdentified().should.be.false; }); diff --git a/packages/concerto-core/test/model/concept.js b/packages/concerto-core/test/model/concept.js index 91dd1952b3..dfbcae6026 100644 --- a/packages/concerto-core/test/model/concept.js +++ b/packages/concerto-core/test/model/concept.js @@ -82,7 +82,7 @@ describe('Concept', function () { asset.invSets = [inventorySets]; const serializer = new Serializer(factory, modelManager); const obj = serializer.toJSON(asset); - JSON.stringify(obj).should.equal('{"$class":"org.acme.biznet.MakerInventory","makerId":"123","invSets":[{"$class":"org.acme.biznet.InventorySets","Make":"Make","Model":"Model","invCount":10,"invType":"NEWBATCH"}]}'); + JSON.stringify(obj).should.equal('{"$class":"org.acme.biznet.MakerInventory","makerId":"123","invSets":[{"$class":"org.acme.biznet.InventorySets","Make":"Make","Model":"Model","invCount":10,"invType":"NEWBATCH"}],"$identifier":"123"}'); }); it('should generate JSON for an asset that contains a concept', function () { diff --git a/packages/concerto-core/test/model/resource.js b/packages/concerto-core/test/model/resource.js index a2030f00b1..09d2534ae7 100644 --- a/packages/concerto-core/test/model/resource.js +++ b/packages/concerto-core/test/model/resource.js @@ -65,6 +65,7 @@ describe('Resource', function () { resource.owner = modelManager.getFactory().newRelationship('org.acme.l1', 'Person', '123'); resource.toJSON().should.deep.equal({ $class: 'org.acme.l1.Car', + $identifier: '456', owner: 'resource:org.acme.l1.Person#123', vin: '456' }); diff --git a/packages/concerto-core/test/models/farm2fork.js b/packages/concerto-core/test/models/farm2fork.js index c94a41be57..05f461f4af 100644 --- a/packages/concerto-core/test/models/farm2fork.js +++ b/packages/concerto-core/test/models/farm2fork.js @@ -50,7 +50,7 @@ describe('Farm2Fork Model', function() { animal.should.not.be.null; animal.getIdentifierFieldName().should.equal('identifier'); animal.getName().should.equal('Animal'); - animal.getProperties().length.should.equal(9); + animal.getProperties().length.should.equal(10); // validator, default let identifierField = animal.getProperty('identifier'); diff --git a/packages/concerto-core/test/models/test.js b/packages/concerto-core/test/models/test.js index 83b3668f0a..09a7a7d1f2 100644 --- a/packages/concerto-core/test/models/test.js +++ b/packages/concerto-core/test/models/test.js @@ -267,7 +267,7 @@ describe('Test Model', function(){ let vehicle = modelFile.getAssetDeclaration('Vehicle'); vehicle.getIdentifierFieldName().should.equal('vin'); vehicle.getName().should.equal('Vehicle'); - vehicle.getProperties().length.should.equal(16); // 15 from Vehicle, and 1 from Base + vehicle.getProperties().length.should.equal(17); // 15 from Vehicle, and 1 from Base, and one from $identifier // validator, default let vinField = vehicle.getProperty('vin'); diff --git a/packages/concerto-core/test/models/wildcards.js b/packages/concerto-core/test/models/wildcards.js index e7ed7ce054..97305ca9f3 100644 --- a/packages/concerto-core/test/models/wildcards.js +++ b/packages/concerto-core/test/models/wildcards.js @@ -72,6 +72,7 @@ describe('Wildcards Model', function () { }; const resource = serializer.fromJSON(json); resource.assetId.should.equal('1'); + resource.$identifier.should.equal('1'); resource.concept.gender.should.equal('FEMALE'); resource.participant.personId.should.equal('1'); resource.participant.firstName.should.equal('Alice'); @@ -102,6 +103,7 @@ describe('Wildcards Model', function () { }; const resource = ergoSerializer.fromJSON(json); resource.assetId.should.equal('1'); + resource.$identifier.should.equal('1'); resource.concept.gender.should.equal('FEMALE'); resource.participant.personId.should.equal('1'); resource.participant.firstName.should.equal('Alice'); @@ -125,6 +127,7 @@ describe('Wildcards Model', function () { json.should.deep.equal({ $class: 'org.acme.wildcards.MyAsset', assetId: '1', + $identifier: '1', concept: { $class: 'org.acme.wildcards.MyConcept', gender: 'FEMALE' diff --git a/packages/concerto-core/test/serializer.js b/packages/concerto-core/test/serializer.js index 97283f1d8a..9b9143d4ef 100644 --- a/packages/concerto-core/test/serializer.js +++ b/packages/concerto-core/test/serializer.js @@ -122,6 +122,7 @@ describe('Serializer', () => { }); json.should.deep.equal({ $class: 'org.acme.sample.SampleAsset', + $identifier: '1', assetId: '1', owner: 'resource:org.acme.sample.SampleParticipant#alice@email.com', stringValue: 'the value', @@ -182,6 +183,7 @@ describe('Serializer', () => { }); json.should.deep.equal({ $class: 'org.acme.sample.SampleAsset', + $identifier: '1', assetId: '1' }); }); @@ -192,6 +194,7 @@ describe('Serializer', () => { let json = serializer.toJSON(resource); json.should.deep.equal({ $class: 'org.acme.sample.SampleAsset', + $identifier: '1', assetId: '1' }); }); @@ -230,6 +233,7 @@ describe('Serializer', () => { }); json.should.deep.equal({ $class: 'org.acme.sample.SampleAsset', + $identifier: '1', assetId: '1', owner: 'resource:org.acme.sample.SampleParticipant#alice@email.com', stringValue: '', @@ -267,6 +271,7 @@ describe('Serializer', () => { let resource = serializer.fromJSON(json); resource.should.be.an.instanceOf(Resource); resource.assetId.should.equal('1'); + resource.$identifier.should.equal('1'); resource.owner.should.be.an.instanceOf(Relationship); resource.stringValue.should.equal('the value'); resource.doubleValue.should.equal(3.14); @@ -345,6 +350,7 @@ describe('Serializer', () => { let resource = serializer.fromJSON(json, { validate: false }); resource.should.be.an.instanceOf(Resource); resource.assetId.should.equal('1'); + resource.$identifier.should.equal('1'); resource.owner.should.be.an.instanceOf(Relationship); should.equal(resource.stringValue, undefined); }); @@ -359,6 +365,7 @@ describe('Serializer', () => { let resource = serializer.fromJSON(json); resource.should.be.an.instanceOf(Resource); resource.assetId.should.equal('1'); + resource.$identifier.should.equal('1'); resource.owner.should.be.an.instanceOf(Relationship); should.equal(resource.stringValue, undefined); }); diff --git a/packages/concerto-core/test/serializer/jsongenerator.js b/packages/concerto-core/test/serializer/jsongenerator.js index f578d9a6d5..6f6426bf34 100644 --- a/packages/concerto-core/test/serializer/jsongenerator.js +++ b/packages/concerto-core/test/serializer/jsongenerator.js @@ -205,7 +205,7 @@ describe('JSONGenerator', () => { }; options.stack.push(resource); let result = jsonGenerator.visitRelationshipDeclaration(relationshipDeclaration1, options); - result.should.deep.equal({ '$class': 'org.acme.MyAsset1', assetId: 'DOGE_1' }); + result.should.deep.equal({ '$class': 'org.acme.MyAsset1', $identifier: 'DOGE_1', assetId: 'DOGE_1' }); }); it('should generate a circular resource if option is specified', () => { @@ -223,7 +223,7 @@ describe('JSONGenerator', () => { }; options.stack.push(resource1); let result = jsonGenerator.visitRelationshipDeclaration(relationshipDeclaration3, options); - result.should.deep.equal({'$class':'org.acme.SimpleAssetCircle','assetId':'DOGE_1','next':{'$class':'org.acme.SimpleAssetCircle','assetId':'DOGE_2','next':{'$class':'org.acme.SimpleAssetCircle','assetId':'DOGE_3','next':'resource:org.acme.SimpleAssetCircle#DOGE_1'}}}); + result.should.deep.equal({'$class':'org.acme.SimpleAssetCircle', '$identifier': 'DOGE_1', 'assetId':'DOGE_1','next':{'$class':'org.acme.SimpleAssetCircle','$identifier': 'DOGE_2','assetId':'DOGE_2','next':{'$class':'org.acme.SimpleAssetCircle','$identifier': 'DOGE_3','assetId':'DOGE_3','next':'resource:org.acme.SimpleAssetCircle#DOGE_1'}}}); }); it('should generate an array of relationships', () => { @@ -262,7 +262,7 @@ describe('JSONGenerator', () => { }; options.stack.push([resource1, resource2]); let result = jsonGenerator.visitRelationshipDeclaration(relationshipDeclaration2, options); - result.should.deep.equal([{ '$class': 'org.acme.MyAsset1', assetId: 'DOGE_1' }, { '$class': 'org.acme.MyAsset1', assetId: 'DOGE_2' }]); + result.should.deep.equal([{ '$class': 'org.acme.MyAsset1', '$identifier': 'DOGE_1', assetId: 'DOGE_1' }, { '$class': 'org.acme.MyAsset1', '$identifier': 'DOGE_2', assetId: 'DOGE_2' }]); }); it('should serialize a circular array of resources if option is specified', () => { @@ -280,7 +280,7 @@ describe('JSONGenerator', () => { }; options.stack.push([resource1, resource2, resource3]); let result = jsonGenerator.visitRelationshipDeclaration(relationshipDeclaration4, options); - result.should.deep.equal([{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_1','next':[{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_2','next':[{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_3','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_1','resource:org.acme.SimpleAssetCircleArray#DOGE_2']},'resource:org.acme.SimpleAssetCircleArray#DOGE_1']},{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_3','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_1',{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_2','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_3','resource:org.acme.SimpleAssetCircleArray#DOGE_1']}]}]},{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_2','next':[{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_3','next':[{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_1','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_2','resource:org.acme.SimpleAssetCircleArray#DOGE_3']},'resource:org.acme.SimpleAssetCircleArray#DOGE_2']},{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_1','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_2',{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_3','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_1','resource:org.acme.SimpleAssetCircleArray#DOGE_2']}]}]},{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_3','next':[{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_1','next':[{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_2','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_3','resource:org.acme.SimpleAssetCircleArray#DOGE_1']},'resource:org.acme.SimpleAssetCircleArray#DOGE_3']},{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_2','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_3',{'$class':'org.acme.SimpleAssetCircleArray','assetId':'DOGE_1','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_2','resource:org.acme.SimpleAssetCircleArray#DOGE_3']}]}]}]); + result.should.deep.equal([{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_1','assetId':'DOGE_1','next':[{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_2','assetId':'DOGE_2','next':[{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_3','assetId':'DOGE_3','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_1','resource:org.acme.SimpleAssetCircleArray#DOGE_2']},'resource:org.acme.SimpleAssetCircleArray#DOGE_1']},{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_3','assetId':'DOGE_3','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_1',{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_2','assetId':'DOGE_2','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_3','resource:org.acme.SimpleAssetCircleArray#DOGE_1']}]}]},{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_2','assetId':'DOGE_2','next':[{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_3','assetId':'DOGE_3','next':[{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_1','assetId':'DOGE_1','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_2','resource:org.acme.SimpleAssetCircleArray#DOGE_3']},'resource:org.acme.SimpleAssetCircleArray#DOGE_2']},{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_1','assetId':'DOGE_1','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_2',{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_3','assetId':'DOGE_3','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_1','resource:org.acme.SimpleAssetCircleArray#DOGE_2']}]}]},{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_3','assetId':'DOGE_3','next':[{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_1','assetId':'DOGE_1','next':[{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_2','assetId':'DOGE_2','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_3','resource:org.acme.SimpleAssetCircleArray#DOGE_1']},'resource:org.acme.SimpleAssetCircleArray#DOGE_3']},{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_2','assetId':'DOGE_2','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_3',{'$class':'org.acme.SimpleAssetCircleArray','$identifier': 'DOGE_1','assetId':'DOGE_1','next':['resource:org.acme.SimpleAssetCircleArray#DOGE_2','resource:org.acme.SimpleAssetCircleArray#DOGE_3']}]}]}]); }); it('should throw if stack contains something other than a Resource or Concept', () => { @@ -748,10 +748,10 @@ describe('JSONGenerator', () => { let result = jsonGenerator.visitField(field,parameters); result.should.deep.equal([ - { '$class': 'org.acme.MyAsset1', assetId: 'child1' }, - { '$class': 'org.acme.MyAsset1', assetId: 'child2' } ]); + { '$class': 'org.acme.MyAsset1', '$identifier': 'child1', assetId: 'child1' }, + { '$class': 'org.acme.MyAsset1', '$identifier': 'child2', assetId: 'child2' } ]); - spy.callCount.should.equal(3); // we call it once at the start, the function recurses into it twice + spy.callCount.should.equal(5); // we call it once at the start, the function recurses into it twice }); }); From e148dfd673dd0340aafb8368b5d191a18d5a270d Mon Sep 17 00:00:00 2001 From: Jerome Simeon Date: Fri, 19 Mar 2021 14:11:34 -0400 Subject: [PATCH 3/3] chore(identifiable) No need to special case identifier field Signed-off-by: Jerome Simeon --- .../concerto-core/lib/introspect/identifieddeclaration.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/concerto-core/lib/introspect/identifieddeclaration.js b/packages/concerto-core/lib/introspect/identifieddeclaration.js index a1ec6e4d7a..eb457a1ac9 100644 --- a/packages/concerto-core/lib/introspect/identifieddeclaration.js +++ b/packages/concerto-core/lib/introspect/identifieddeclaration.js @@ -47,11 +47,6 @@ class IdentifiedDeclaration extends ClassDeclaration { */ process() { super.process(); - - if(this.superType === 'Concept' && !this.idField) { - this.idField = '$identifier'; - this.addIdentifierField(); - } } /**