diff --git a/lib/codegen/fromcto/odata/odatavisitor.js b/lib/codegen/fromcto/odata/odatavisitor.js index c003ae52..b3c5bc33 100644 --- a/lib/codegen/fromcto/odata/odatavisitor.js +++ b/lib/codegen/fromcto/odata/odatavisitor.js @@ -63,7 +63,7 @@ class ODataVisitor { } else if (thing.isClassDeclaration?.()) { return this.visitClassDeclaration(thing, parameters); } else if (thing.isMapDeclaration?.()) { - return; + return this.visitMapDeclaration(thing, parameters); } else if (thing.isTypeScalar?.()) { return this.visitField(thing.getScalarField(), parameters); } else if (thing.isField?.()) { @@ -280,6 +280,43 @@ class ODataVisitor { return null; } + /** + * Visitor design pattern + * @param {MapDeclaration} mapDeclaration - the object being visited + * @param {Object} parameters - the parameter + * @return {Object} the result of visiting or null + * @private + */ + visitMapDeclaration(mapDeclaration, parameters) { + let keyType = mapDeclaration.getKey().getType(); + let valueType = mapDeclaration.getValue().getType(); + + if (ModelUtil.isPrimitiveType(keyType)) { + keyType = this.toODataType(keyType); + } else if (ModelUtil.isScalar(mapDeclaration.getKey())) { + const scalarDeclaration = mapDeclaration.getModelFile().getType(mapDeclaration.getKey().getType()); + const scalarType = scalarDeclaration.getType(); + keyType = this.toODataType(scalarType); + } + + if (ModelUtil.isPrimitiveType(valueType)) { + valueType = this.toODataType(valueType); + } else if (ModelUtil.isScalar(mapDeclaration.getValue())) { + const scalarDeclaration = mapDeclaration.getModelFile().getType(mapDeclaration.getValue().getType()); + const scalarType = scalarDeclaration.getType(); + valueType = this.toODataType(scalarType); + } else { + valueType = ModelUtil.removeNamespaceVersionFromFullyQualifiedName(mapDeclaration.getModelFile().getFullyQualifiedTypeName(valueType)); + } + + parameters.fileWriter.writeLine(1, ``); + parameters.fileWriter.writeLine(2, ``); + parameters.fileWriter.writeLine(2, ``); + parameters.fileWriter.writeLine(1, ''); + + return null; + } + /** * Visitor design pattern * @param {Relationship} relationship - the object being visited diff --git a/test/codegen/__snapshots__/codegen.js.snap b/test/codegen/__snapshots__/codegen.js.snap index 27f4b951..75ce707b 100644 --- a/test/codegen/__snapshots__/codegen.js.snap +++ b/test/codegen/__snapshots__/codegen.js.snap @@ -2686,6 +2686,10 @@ exports[`codegen #formats check we can convert all formats from namespace unvers + + + + @@ -2723,6 +2727,30 @@ exports[`codegen #formats check we can convert all formats from namespace unvers + + + + + + + + + + + + + + + + + + + + + + + + @@ -8660,6 +8688,10 @@ exports[`codegen #formats check we can convert all formats from namespace versio + + + + @@ -8697,6 +8729,30 @@ exports[`codegen #formats check we can convert all formats from namespace versio + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/codegen/fromcto/odata/odatavisitor.js b/test/codegen/fromcto/odata/odatavisitor.js index a329c2a6..8694bbf1 100644 --- a/test/codegen/fromcto/odata/odatavisitor.js +++ b/test/codegen/fromcto/odata/odatavisitor.js @@ -19,9 +19,13 @@ chai.should(); const sinon = require('sinon'); const ODataVisitor = require('../../../../lib/codegen/fromcto/odata/odatavisitor.js'); +const { ConceptDeclaration } = require('@accordproject/concerto-core'); const ClassDeclaration = require('@accordproject/concerto-core').ClassDeclaration; +const ScalarDeclaration = require('@accordproject/concerto-core').ScalarDeclaration; const EnumDeclaration = require('@accordproject/concerto-core').EnumDeclaration; +const MapDeclaration = require('@accordproject/concerto-core').MapDeclaration; +const ModelUtil = require('@accordproject/concerto-core').ModelUtil; const EnumValueDeclaration = require('@accordproject/concerto-core').EnumValueDeclaration; const Field = require('@accordproject/concerto-core').Field; const ModelFile = require('@accordproject/concerto-core').ModelFile; @@ -30,6 +34,8 @@ const RelationshipDeclaration = require('@accordproject/concerto-core').Relation const Decorator = require('@accordproject/concerto-core').Decorator; const FileWriter = require('@accordproject/concerto-util').FileWriter; +let sandbox = sinon.createSandbox(); + describe('ODataVisitor', function () { let oDataVisitor; let mockFileWriter; @@ -326,6 +332,164 @@ describe('ODataVisitor', function () { }); }); + describe('visitMapDeclaration', () => { + it('should write the map ', () => { + let param = { + fileWriter: mockFileWriter + }; + + let mockModelFile = sinon.createStubInstance(ModelFile); + let mockMapDeclaration = sinon.createStubInstance(MapDeclaration); + + const getKeyType = sinon.stub(); + const getValueType = sinon.stub(); + + getKeyType.returns('String'); + getValueType.returns('String'); + + mockModelFile.getType.returns(mockMapDeclaration); + mockMapDeclaration.getName.returns('MockMap'); + mockMapDeclaration.getKey.returns({getType: getKeyType}); + mockMapDeclaration.getValue.returns({getType: getValueType}); + + const isPrimitiveTypeStub = sandbox.stub(ModelUtil, 'isPrimitiveType'); + + isPrimitiveTypeStub.onCall(0).returns(true); + isPrimitiveTypeStub.onCall(1).returns(true); + + oDataVisitor.visitMapDeclaration(mockMapDeclaration, param); + + param.fileWriter.writeLine.withArgs(1, '').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(2, '').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(2, '').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(1, '').calledOnce.should.be.ok; + isPrimitiveTypeStub.restore(); + }); + + it('should write the map ', () => { + let param = { + fileWriter: mockFileWriter + }; + + let mockModelFile = sinon.createStubInstance(ModelFile); + let mockMapDeclaration = sinon.createStubInstance(MapDeclaration); + let mockScalarDeclaration = sinon.createStubInstance(ScalarDeclaration); + + + const getKeyType = sinon.stub(); + const getValueType = sinon.stub(); + + getKeyType.returns('SSN'); + getValueType.returns('String'); + + mockMapDeclaration.getName.returns('MockMap'); + mockMapDeclaration.getKey.returns({getType: getKeyType}); + mockMapDeclaration.getValue.returns({getType: getValueType}); + mockMapDeclaration.getModelFile.returns(mockModelFile); + mockModelFile.getType.returns(mockScalarDeclaration); + mockScalarDeclaration.getType.returns('String'); + + const isPrimitiveTypeStub = sandbox.stub(ModelUtil, 'isPrimitiveType'); + const isScalarStub = sandbox.stub(ModelUtil, 'isScalar'); + + isPrimitiveTypeStub.onCall(0).returns(false); + isPrimitiveTypeStub.onCall(1).returns(true); + + isScalarStub.onCall(0).returns(true); + isScalarStub.onCall(1).returns(false); + + oDataVisitor.visitMapDeclaration(mockMapDeclaration, param); + + param.fileWriter.writeLine.withArgs(1, '').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(2, '').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(2, '').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(1, '').calledOnce.should.be.ok; + isPrimitiveTypeStub.restore(); + isScalarStub.restore(); + }); + + it('should write the map ', () => { + let param = { + fileWriter: mockFileWriter + }; + + let mockModelFile = sinon.createStubInstance(ModelFile); + let mockMapDeclaration = sinon.createStubInstance(MapDeclaration); + let mockScalarDeclaration = sinon.createStubInstance(ScalarDeclaration); + + const getKeyType = sinon.stub(); + const getValueType = sinon.stub(); + + getKeyType.returns('SSN'); + getValueType.returns('SSN'); + + mockMapDeclaration.getName.returns('MockMap'); + mockMapDeclaration.getKey.returns({getType: getKeyType}); + mockMapDeclaration.getValue.returns({getType: getValueType}); + mockMapDeclaration.getModelFile.returns(mockModelFile); + mockModelFile.getType.returns(mockScalarDeclaration); + mockScalarDeclaration.getType.returns('String'); + + const isPrimitiveTypeStub = sandbox.stub(ModelUtil, 'isPrimitiveType'); + const isScalarStub = sandbox.stub(ModelUtil, 'isScalar'); + + isPrimitiveTypeStub.onCall(0).returns(false); + isPrimitiveTypeStub.onCall(1).returns(false); + + isScalarStub.onCall(0).returns(true); + isScalarStub.onCall(1).returns(true); + + oDataVisitor.visitMapDeclaration(mockMapDeclaration, param); + + param.fileWriter.writeLine.withArgs(1, '').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(2, '').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(2, '').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(1, '').calledOnce.should.be.ok; + isPrimitiveTypeStub.restore(); + isScalarStub.restore(); + }); + + it('should write the map ', () => { + let param = { + fileWriter: mockFileWriter + }; + + let mockModelFile = sinon.createStubInstance(ModelFile); + let mockMapDeclaration = sinon.createStubInstance(MapDeclaration); + let mockConceptDeclaration = sinon.createStubInstance(ConceptDeclaration); + + const getKeyType = sinon.stub(); + const getValueType = sinon.stub(); + + getKeyType.returns('String'); + getValueType.returns('Person'); + + mockMapDeclaration.getName.returns('MockMap'); + mockMapDeclaration.getKey.returns({getType: getKeyType}); + mockMapDeclaration.getValue.returns({getType: getValueType}); + mockMapDeclaration.getModelFile.returns(mockModelFile); + mockModelFile.getType.returns(mockConceptDeclaration); + mockModelFile.getFullyQualifiedTypeName.returns('com.acme@1.0.0.Person'); + + const isPrimitiveTypeStub = sandbox.stub(ModelUtil, 'isPrimitiveType'); + const isScalarStub = sandbox.stub(ModelUtil, 'isScalar'); + + isPrimitiveTypeStub.onCall(0).returns(true); + isPrimitiveTypeStub.onCall(1).returns(false); + + isScalarStub.onCall(0).returns(false); + + oDataVisitor.visitMapDeclaration(mockMapDeclaration, param); + + param.fileWriter.writeLine.withArgs(1, '').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(2, '').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(2, '').calledOnce.should.be.ok; + param.fileWriter.writeLine.withArgs(1, '').calledOnce.should.be.ok; + isPrimitiveTypeStub.restore(); + isScalarStub.restore(); + }); + }); + describe('visitClassDeclaration', () => { let param; beforeEach(() => {