Skip to content

Commit 2a76a0c

Browse files
authored
feat(tools): add a mermaid visitor (#530)
1 parent ac47ec0 commit 2a76a0c

File tree

6 files changed

+370
-2
lines changed

6 files changed

+370
-2
lines changed

packages/concerto-tools/lib/codegen/codegen.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const JavaVisitor = require('./fromcto/java/javavisitor');
2525
const GraphQLVisitor = require('./fromcto/graphql/graphqlvisitor');
2626
const CSharpVisitor = require('./fromcto/csharp/csharpvisitor');
2727
const ODataVisitor = require('./fromcto/odata/odatavisitor');
28+
const MermaidVisitor = require('./fromcto/mermaid/mermaidvisitor');
2829

2930
module.exports = {
3031
AbstractPlugin,
@@ -37,6 +38,7 @@ module.exports = {
3738
GraphQLVisitor,
3839
CSharpVisitor,
3940
ODataVisitor,
41+
MermaidVisitor,
4042
formats: {
4143
golang: GoLangVisitor,
4244
jsonschema: JSONSchemaVisitor,
@@ -46,6 +48,7 @@ module.exports = {
4648
java: JavaVisitor,
4749
graphql: GraphQLVisitor,
4850
csharp: CSharpVisitor,
49-
odata: ODataVisitor
51+
odata: ODataVisitor,
52+
mermaid: MermaidVisitor
5053
}
5154
};
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
'use strict';
16+
17+
/**
18+
* Convert the contents of a ModelManager
19+
* to Mermaid format file.
20+
* Set a fileWriter property (instance of FileWriter) on the parameters
21+
* object to control where the generated code is written to disk.
22+
*
23+
* @private
24+
* @class
25+
*/
26+
class MermaidVisitor {
27+
/**
28+
* Visitor design pattern
29+
* @param {Object} thing - the object being visited
30+
* @param {Object} parameters - the parameter
31+
* @return {Object} the result of visiting or null
32+
* @private
33+
*/
34+
visit(thing, parameters) {
35+
if (thing.isModelManager?.()) {
36+
return this.visitModelManager(thing, parameters);
37+
} else if (thing.isModelFile?.()) {
38+
return this.visitModelFile(thing, parameters);
39+
} else if (thing.isParticipant?.()) {
40+
return this.visitParticipantDeclaration(thing, parameters);
41+
} else if (thing.isTransaction?.()) {
42+
return this.visitTransactionDeclaration(thing, parameters);
43+
} else if (thing.isEvent?.()) {
44+
return this.visitEventDeclaration(thing, parameters);
45+
} else if (thing.isAsset?.()) {
46+
return this.visitAssetDeclaration(thing, parameters);
47+
} else if (thing.isEnum?.()) {
48+
return this.visitEnumDeclaration(thing, parameters);
49+
} else if (thing.isClassDeclaration?.()) {
50+
return this.visitClassDeclaration(thing, parameters);
51+
} else if (thing.isField?.()) {
52+
return this.visitField(thing, parameters);
53+
} else if (thing.isRelationship?.()) {
54+
return this.visitRelationship(thing, parameters);
55+
} else if (thing.isEnumValue?.()) {
56+
return this.visitEnumValueDeclaration(thing, parameters);
57+
} else {
58+
throw new Error('Unrecognised ' + JSON.stringify(thing) );
59+
}
60+
}
61+
62+
/**
63+
* Visitor design pattern
64+
* @param {ModelManager} modelManager - the object being visited
65+
* @param {Object} parameters - the parameter
66+
* @return {Object} the result of visiting or null
67+
* @private
68+
*/
69+
visitModelManager(modelManager, parameters) {
70+
parameters.fileWriter.openFile('model.mmd');
71+
parameters.fileWriter.writeLine(0, 'classDiagram');
72+
73+
modelManager.getModelFiles().forEach((decl) => {
74+
decl.accept(this, parameters);
75+
});
76+
77+
parameters.fileWriter.closeFile();
78+
79+
return null;
80+
}
81+
82+
/**
83+
* Visitor design pattern
84+
* @param {ModelFile} modelFile - the object being visited
85+
* @param {Object} parameters - the parameter
86+
* @return {Object} the result of visiting or null
87+
* @private
88+
*/
89+
visitModelFile(modelFile, parameters) {
90+
modelFile.getAllDeclarations().forEach((decl) => {
91+
decl.accept(this, parameters);
92+
});
93+
return null;
94+
}
95+
96+
/**
97+
* Visitor design pattern
98+
* @param {ClassDeclaration} classDeclaration - the object being visited
99+
* @param {Object} parameters - the parameter
100+
* @return {Object} the result of visiting or null
101+
* @private
102+
*/
103+
visitAssetDeclaration(classDeclaration, parameters) {
104+
return this.visitClassDeclaration(classDeclaration, parameters, 'asset');
105+
}
106+
107+
/**
108+
* Visitor design pattern
109+
* @param {ClassDeclaration} classDeclaration - the object being visited
110+
* @param {Object} parameters - the parameter
111+
* @return {Object} the result of visiting or null
112+
* @private
113+
*/
114+
visitEnumDeclaration(classDeclaration, parameters) {
115+
return this.visitClassDeclaration(classDeclaration, parameters, 'enumeration');
116+
}
117+
118+
/**
119+
* Visitor design pattern
120+
* @param {ClassDeclaration} classDeclaration - the object being visited
121+
* @param {Object} parameters - the parameter
122+
* @return {Object} the result of visiting or null
123+
* @private
124+
*/
125+
visitEventDeclaration(classDeclaration, parameters) {
126+
return this.visitClassDeclaration(classDeclaration, parameters, 'event');
127+
}
128+
129+
/**
130+
* Visitor design pattern
131+
* @param {ClassDeclaration} classDeclaration - the object being visited
132+
* @param {Object} parameters - the parameter
133+
* @return {Object} the result of visiting or null
134+
* @private
135+
*/
136+
visitParticipantDeclaration(classDeclaration, parameters) {
137+
return this.visitClassDeclaration(classDeclaration, parameters, 'participant');
138+
}
139+
140+
/**
141+
* Visitor design pattern
142+
* @param {ClassDeclaration} classDeclaration - the object being visited
143+
* @param {Object} parameters - the parameter
144+
* @return {Object} the result of visiting or null
145+
* @private
146+
*/
147+
visitTransactionDeclaration(classDeclaration, parameters) {
148+
return this.visitClassDeclaration(classDeclaration, parameters, 'transaction');
149+
}
150+
151+
152+
/**
153+
* Visitor design pattern
154+
* @param {ClassDeclaration} classDeclaration - the object being visited
155+
* @param {Object} parameters - the parameter
156+
* @param {string} type - the type of the declaration
157+
* @return {Object} the result of visiting or null
158+
* @private
159+
*/
160+
visitClassDeclaration(classDeclaration, parameters, type = 'concept') {
161+
162+
if (classDeclaration.getOwnProperties().length > 0) {
163+
parameters.fileWriter.writeLine(0, 'class ' + classDeclaration.getName() + ' {');
164+
parameters.fileWriter.writeLine(0, '<< ' + type + '>>');
165+
166+
classDeclaration.getOwnProperties().forEach((property) => {
167+
if (!property.isRelationship?.()) {
168+
property.accept(this, parameters);
169+
}
170+
});
171+
172+
parameters.fileWriter.writeLine(0, '}\n');
173+
}
174+
else {
175+
parameters.fileWriter.writeLine(0, 'class ' + classDeclaration.getName());
176+
parameters.fileWriter.writeLine(0, '<< ' + type + '>>' + ' ' + classDeclaration.getName() + '\n');
177+
}
178+
179+
classDeclaration.getOwnProperties().forEach((property) => {
180+
if (property.isRelationship?.()) {
181+
property.accept(this, parameters);
182+
}
183+
});
184+
185+
if (classDeclaration.getSuperType()) {
186+
parameters.fileWriter.writeLine(0, classDeclaration.getName() + ' --|> ' + classDeclaration.getSuperTypeDeclaration().getName());
187+
}
188+
189+
return null;
190+
}
191+
192+
/**
193+
* Visitor design pattern
194+
* @param {Field} field - the object being visited
195+
* @param {Object} parameters - the parameter
196+
* @return {Object} the result of visiting or null
197+
* @private
198+
*/
199+
visitField(field, parameters) {
200+
let array = '';
201+
202+
if (field.isArray()) {
203+
array = '[]';
204+
}
205+
206+
parameters.fileWriter.writeLine(1, ' +' + field.getType() + array + ' ' + field.getName());
207+
208+
return null;
209+
}
210+
211+
/**
212+
* Visitor design pattern
213+
* @param {EnumValueDeclaration} enumValueDeclaration - the object being visited
214+
* @param {Object} parameters - the parameter
215+
* @return {Object} the result of visiting or null
216+
* @private
217+
*/
218+
visitEnumValueDeclaration(enumValueDeclaration, parameters) {
219+
parameters.fileWriter.writeLine(1, enumValueDeclaration.getName());
220+
return null;
221+
}
222+
223+
/**
224+
* Visitor design pattern
225+
* @param {RelationshipDeclaration} relationship - the object being visited
226+
* @param {Object} parameters - the parameter
227+
* @return {Object} the result of visiting or null
228+
* @private
229+
*/
230+
visitRelationship(relationship, parameters) {
231+
let array = '"1"';
232+
if (relationship.isArray()) {
233+
array = '"*"';
234+
}
235+
parameters.fileWriter.writeLine(0, relationship.getParent().getName() + ' "1"' + ' o-- ' + array + ' ' + relationship.getType() + ' : ' + relationship.getName());
236+
return null;
237+
}
238+
}
239+
240+
module.exports = MermaidVisitor;

packages/concerto-tools/test/codegen/fromcto/data/model/hr.cto

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,16 @@ participant Contractor extends Person {
6767

6868
participant Manager extends Employee {
6969
--> Person[] reports optional
70+
}
71+
72+
event CompanyEvent {
73+
}
74+
75+
event Onboarded extends CompanyEvent {
76+
--> Employee employee
77+
}
78+
79+
transaction ChangeOfAddress {
80+
--> Person Person
81+
o Address newAddress
7082
}

packages/concerto-tools/types/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export var CodeGen: {
99
GraphQLVisitor: typeof import("./lib/codegen/fromcto/graphql/graphqlvisitor");
1010
CSharpVisitor: typeof import("./lib/codegen/fromcto/csharp/csharpvisitor");
1111
ODataVisitor: typeof import("./lib/codegen/fromcto/odata/odatavisitor");
12+
MermaidVisitor: typeof import("./lib/codegen/fromcto/mermaid/mermaidvisitor");
1213
formats: {
1314
golang: typeof import("./lib/codegen/fromcto/golang/golangvisitor");
1415
jsonschema: typeof import("./lib/codegen/fromcto/jsonschema/jsonschemavisitor");
@@ -19,6 +20,7 @@ export var CodeGen: {
1920
graphql: typeof import("./lib/codegen/fromcto/graphql/graphqlvisitor");
2021
csharp: typeof import("./lib/codegen/fromcto/csharp/csharpvisitor");
2122
odata: typeof import("./lib/codegen/fromcto/odata/odatavisitor");
23+
mermaid: typeof import("./lib/codegen/fromcto/mermaid/mermaidvisitor");
2224
};
2325
};
2426
export var version: any;

packages/concerto-tools/types/lib/codegen/codegen.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import JavaVisitor = require("./fromcto/java/javavisitor");
88
import GraphQLVisitor = require("./fromcto/graphql/graphqlvisitor");
99
import CSharpVisitor = require("./fromcto/csharp/csharpvisitor");
1010
import ODataVisitor = require("./fromcto/odata/odatavisitor");
11+
import MermaidVisitor = require("./fromcto/mermaid/mermaidvisitor");
1112
export declare namespace formats {
1213
export { GoLangVisitor as golang };
1314
export { JSONSchemaVisitor as jsonschema };
@@ -18,5 +19,6 @@ export declare namespace formats {
1819
export { GraphQLVisitor as graphql };
1920
export { CSharpVisitor as csharp };
2021
export { ODataVisitor as odata };
22+
export { MermaidVisitor as mermaid };
2123
}
22-
export { AbstractPlugin, GoLangVisitor, JSONSchemaVisitor, XmlSchemaVisitor, PlantUMLVisitor, TypescriptVisitor, JavaVisitor, GraphQLVisitor, CSharpVisitor, ODataVisitor };
24+
export { AbstractPlugin, GoLangVisitor, JSONSchemaVisitor, XmlSchemaVisitor, PlantUMLVisitor, TypescriptVisitor, JavaVisitor, GraphQLVisitor, CSharpVisitor, ODataVisitor, MermaidVisitor };

0 commit comments

Comments
 (0)