1[comment encoding = UTF-8 /]
2[module UML2Swift('http://www.example.org/uml')]
3
4[comment]
5 UML to Swift Code Generator
6 Generates Swift source code from UML class diagrams
7[/comment]
8
9[comment ================================================================ /]
10[comment MAIN ENTRY POINT /]
11[comment ================================================================ /]
12
13[template main(pkg : Package)]
14[comment Generate one file per classifier /]
15[for (cls : Class | pkg.classifiers->filter(Class))]
16[generateClassFile(cls)/]
17[/for]
18[for (proto : Protocol | pkg.classifiers->filter(Protocol))]
19[generateProtocolFile(proto)/]
20[/for]
21[for (enum : Enumeration | pkg.classifiers->filter(Enumeration))]
22[generateEnumFile(enum)/]
23[/for]
24[/template]
25
26[comment ================================================================ /]
27[comment CLASS GENERATION /]
28[comment ================================================================ /]
29
30[template generateClassFile(cls : Class)]
31[file (cls.name + '.swift', 'overwrite', 'UTF-8')]
32//
33// [cls.name/].swift
34// Generated from UML model
35//
36
37import Foundation
38
39[if (cls.documentation <> null)]
40/// [cls.documentation/]
41[/if]
42[generateClassDeclaration(cls)/]
43[/file]
44[/template]
45
46[template generateClassDeclaration(cls : Class)]
47[if (cls.isFinal)]final [/if][if (cls.isStruct)]struct[else]class[/if] [cls.name/][generateInheritance(cls)/] {
48
49 // MARK: - Properties
50
51[for (prop : Property | cls.properties)]
52 [generateProperty(prop)/]
53[/for]
54
55 // MARK: - Initialisation
56
57 [generateInitialiser(cls)/]
58
59 // MARK: - Methods
60
61[for (op : Operation | cls.operations)]
62 [generateOperation(op)/]
63[/for]
64}
65[/template]
66
67[template generateInheritance(cls : Class)]
68[if (cls.superClass <> null or cls.protocols->notEmpty())]
69: [if (cls.superClass <> null)][cls.superClass.name/][if (cls.protocols->notEmpty())], [/if][/if][cls.protocols.name->sep(', ')/][/if]
70[/template]
71
72[template generateInitialiser(cls : Class)]
73[let requiredProps = cls.properties->select(p | p.defaultValue = null and not p.isOptional)]
74[if (requiredProps->notEmpty())]
75init([for (p : Property | requiredProps) separator(', ')][p.name/]: [generateTypeName(p)/][/for]) {
76[for (p : Property | requiredProps)]
77 self.[p.name/] = [p.name/]
78[/for]
79 }
80[else]
81init() {
82 }
83[/if]
84[/let]
85[/template]
86
87[comment ================================================================ /]
88[comment PROPERTY GENERATION /]
89[comment ================================================================ /]
90
91[template generateProperty(prop : Property)]
92[if (prop.isStatic)]static [/if][if (prop.isReadOnly)]let[else]var[/if] [prop.name/]: [generateTypeName(prop)/][generateDefaultValue(prop)/]
93[/template]
94
95[template generateTypeName(prop : TypedElement)]
96[if (prop.isCollection)]['[' + prop.type.name + ']'/][else][prop.type.name/][/if][if (prop.isOptional)]?[/if]
97[/template]
98
99[template generateDefaultValue(prop : Property)]
100[if (prop.defaultValue <> null)] = [prop.defaultValue/][elseif (prop.isOptional)] = nil[elseif (prop.isCollection)] = ['[]'/][/if]
101[/template]
102
103[comment ================================================================ /]
104[comment OPERATION GENERATION /]
105[comment ================================================================ /]
106
107[template generateOperation(op : Operation)]
108[if (op.isStatic)]static [/if]func [op.name/]([generateParameters(op)/])[if (op.isAsync)] async[/if][if (op.throws)] throws[/if][generateReturnType(op)/] {
109 // TODO: Implement [op.name/]
110 [generateReturnStub(op)/]
111 }
112[/template]
113
114[template generateParameters(op : Operation)]
115[for (p : Parameter | op.parameters) separator(', ')]
116[if (p.label <> null and p.label <> p.name)][p.label/] [/if][p.name/]: [if (p.isCollection)]['[' + p.type.name + ']'/][else][p.type.name/][/if][if (p.isOptional)]?[/if][if (p.defaultValue <> null)] = [p.defaultValue/][/if][/for]
117[/template]
118
119[template generateReturnType(op : Operation)]
120[if (op.returnType <> null)] -> [op.returnType.name/][/if]
121[/template]
122
123[template generateReturnStub(op : Operation)]
124[if (op.returnType <> null)]
125[if (op.returnType.name = 'String')]return ""
126[elseif (op.returnType.name = 'Int' or op.returnType.name = 'Double')]return 0
127[elseif (op.returnType.name = 'Bool')]return false
128[else]fatalError("Not implemented")
129[/if]
130[/if]
131[/template]
132
133[comment ================================================================ /]
134[comment PROTOCOL GENERATION /]
135[comment ================================================================ /]
136
137[template generateProtocolFile(proto : Protocol)]
138[file (proto.name + '.swift', 'overwrite', 'UTF-8')]
139//
140// [proto.name/].swift
141// Generated from UML model
142//
143
144import Foundation
145
146[if (proto.documentation <> null)]
147/// [proto.documentation/]
148[/if]
149protocol [proto.name/][if (proto.extends->notEmpty())]: [proto.extends.name->sep(', ')/][/if] {
150[for (prop : Property | proto.properties)]
151 var [prop.name/]: [generateTypeName(prop)/] { get[if (not prop.isReadOnly)] set[/if] }
152[/for]
153[for (op : Operation | proto.operations)]
154 func [op.name/]([generateParameters(op)/])[if (op.isAsync)] async[/if][if (op.throws)] throws[/if][generateReturnType(op)/]
155[/for]
156}
157[/file]
158[/template]
159
160[comment ================================================================ /]
161[comment ENUMERATION GENERATION /]
162[comment ================================================================ /]
163
164[template generateEnumFile(enum : Enumeration)]
165[file (enum.name + '.swift', 'overwrite', 'UTF-8')]
166//
167// [enum.name/].swift
168// Generated from UML model
169//
170
171import Foundation
172
173[if (enum.documentation <> null)]
174/// [enum.documentation/]
175[/if]
176enum [enum.name/][if (enum.rawType <> null)]: [enum.rawType.name/][/if] {
177[for (lit : EnumLiteral | enum.literals)]
178 case [lit.name/][if (lit.rawValue <> null)] = [lit.rawValue/][/if]
179[/for]
180}
181[/file]
182[/template]