1 |
gerard.lemson |
148 |
<?xml version="1.0" encoding="UTF-8"?> |
2 |
gerard.lemson |
208 |
<!-- |
3 |
|
|
This XSLT script transforms a data model from our |
4 |
bourges.laurent |
238 |
intermediate representation to a relational database |
5 |
gerard.lemson |
208 |
Data Definition Language script. |
6 |
gerard.lemson |
148 |
|
7 |
gerard.lemson |
208 |
It depends on our assumed object-relational mapping |
8 |
|
|
prescription and should be compatible with the persistence |
9 |
|
|
framework used for example in the Java/JPA generation. |
10 |
|
|
|
11 |
|
|
We also generate view definitions representing each objectType. |
12 |
|
|
|
13 |
|
|
We assume that all tables are in a single schema. |
14 |
|
|
For now we assume that objectType's names are unique over the complete model. |
15 |
|
|
TODO We need to check this explicitly and modify the generation if not. |
16 |
|
|
|
17 |
|
|
--> |
18 |
|
|
|
19 |
gerard.lemson |
148 |
<!DOCTYPE stylesheet [ |
20 |
|
|
<!ENTITY cr "<xsl:text> |
21 |
|
|
</xsl:text>"> |
22 |
|
|
<!ENTITY bl "<xsl:text> </xsl:text>"> |
23 |
bourges.laurent |
197 |
<!ENTITY tab "<xsl:text> </xsl:text>"> |
24 |
gerard.lemson |
148 |
]> |
25 |
|
|
|
26 |
|
|
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> |
27 |
|
|
|
28 |
|
|
|
29 |
bourges.laurent |
251 |
<xsl:output method="text" encoding="UTF-8" indent="no" /> |
30 |
bourges.laurent |
197 |
|
31 |
gerard.lemson |
148 |
<xsl:strip-space elements="*" /> |
32 |
|
|
|
33 |
gerard.lemson |
229 |
<xsl:key name="element" match="*//*" use="@xmiid"/> |
34 |
|
|
|
35 |
|
|
|
36 |
bourges.laurent |
166 |
<xsl:param name="xmlLastModified"/> |
37 |
|
|
<xsl:param name="xslLastModified"/> |
38 |
gerard.lemson |
148 |
|
39 |
bourges.laurent |
155 |
|
40 |
gerard.lemson |
219 |
<xsl:param name="schema"/> <!-- select="'SNAP.'" --> |
41 |
bourges.laurent |
238 |
|
42 |
|
|
<!-- define the OR mapping type --> |
43 |
gerard.lemson |
234 |
<xsl:variable name="ORMapping_hierarchical" select="'hierarchical'"/> |
44 |
|
|
<xsl:variable name="ORMapping_joined" select="'joined'"/> |
45 |
|
|
<xsl:variable name="ORMapping_class" select="'class'"/> |
46 |
|
|
<xsl:param name="ORMapping" select="$ORMapping_joined"/> |
47 |
gerard.lemson |
148 |
|
48 |
bourges.laurent |
238 |
<!-- modification timestamp --> |
49 |
bourges.laurent |
166 |
<xsl:variable name="lastModified"> |
50 |
|
|
<xsl:choose> |
51 |
|
|
<xsl:when test="number(/model/lastModifiedDate) > number($xslLastModified)"><xsl:value-of select="/model/lastModifiedDate"/></xsl:when> |
52 |
|
|
<xsl:otherwise><xsl:value-of select="$xslLastModified"/></xsl:otherwise> |
53 |
|
|
</xsl:choose> |
54 |
|
|
</xsl:variable> |
55 |
bourges.laurent |
238 |
|
56 |
gerard.lemson |
230 |
<!-- next two might also be parameters, or obtained from a config file --> |
57 |
gerard.lemson |
219 |
<xsl:variable name="defaultVarcharLength" select="'256'"/> |
58 |
gerard.lemson |
230 |
<xsl:variable name="longstringtype" select="'text'"/> <!-- SQLServer specific --> |
59 |
gerard.lemson |
148 |
|
60 |
bourges.laurent |
238 |
|
61 |
|
|
|
62 |
|
|
|
63 |
gerard.lemson |
148 |
<xsl:template match="/"> |
64 |
|
|
<xsl:apply-templates select="model"/> |
65 |
|
|
</xsl:template> |
66 |
|
|
|
67 |
|
|
|
68 |
|
|
|
69 |
|
|
|
70 |
|
|
<xsl:template match="model"> |
71 |
|
|
<xsl:message>Model = <xsl:value-of select="name"></xsl:value-of></xsl:message> |
72 |
bourges.laurent |
197 |
|
73 |
bourges.laurent |
238 |
-- last modification date of the UML model <xsl:value-of select="$lastModified"/>&cr; |
74 |
|
|
|
75 |
|
|
<xsl:choose> |
76 |
|
|
<xsl:when test="$ORMapping = $ORMapping_joined"> |
77 |
|
|
<xsl:apply-templates select=".//objectType" mode="joined"/> |
78 |
|
|
</xsl:when> |
79 |
|
|
<xsl:otherwise> |
80 |
|
|
<xsl:apply-templates select=".//objectType[not(extends)]" mode="hierarchical"/> |
81 |
|
|
</xsl:otherwise> |
82 |
gerard.lemson |
246 |
</xsl:choose> |
83 |
bourges.laurent |
238 |
|
84 |
gerard.lemson |
148 |
</xsl:template> |
85 |
|
|
|
86 |
|
|
|
87 |
bourges.laurent |
238 |
|
88 |
|
|
|
89 |
gerard.lemson |
234 |
<xsl:template match="objectType" mode="hierarchical"> |
90 |
bourges.laurent |
238 |
<!-- generate a single table for the whole object hierarchy below the matched objectType --> |
91 |
gerard.lemson |
234 |
<xsl:variable name="tableName"> |
92 |
|
|
<xsl:apply-templates select="." mode="tableName"/> |
93 |
|
|
</xsl:variable> |
94 |
gerard.lemson |
229 |
<xsl:variable name="containers"> |
95 |
|
|
</xsl:variable> |
96 |
bourges.laurent |
251 |
CREATE TABLE <xsl:value-of select="$tableName"/> ( |
97 |
bourges.laurent |
238 |
id bigint not null |
98 |
|
|
<xsl:apply-templates select="." mode="containers"/> |
99 |
|
|
<xsl:apply-templates select="." mode="hierarchy"/> |
100 |
|
|
);&cr;&cr; |
101 |
gerard.lemson |
148 |
</xsl:template> |
102 |
|
|
|
103 |
|
|
|
104 |
bourges.laurent |
238 |
|
105 |
|
|
|
106 |
gerard.lemson |
229 |
<xsl:template match="objectType" mode="containers"> |
107 |
|
|
<xsl:variable name="xmiid" select="@xmiid"/> |
108 |
|
|
<xsl:if test="/model//objectType[collection/datatype/@xmiidref = $xmiid]"> |
109 |
bourges.laurent |
238 |
, containerId bigint not null -- <xsl:value-of select="/model//objectType[collection/datatype/@xmiidref = $xmiid]/name"/> |
110 |
gerard.lemson |
229 |
</xsl:if> |
111 |
|
|
<xsl:apply-templates select="/model//objectType[extends/datatype/@xmiidref = $xmiid]" mode="containers"/> |
112 |
gerard.lemson |
232 |
</xsl:template> |
113 |
|
|
|
114 |
gerard.lemson |
229 |
|
115 |
bourges.laurent |
238 |
|
116 |
|
|
|
117 |
gerard.lemson |
219 |
<xsl:template match="objectType" mode="hierarchy"> |
118 |
|
|
<xsl:variable name="xmiid" select="@xmiid"/> |
119 |
bourges.laurent |
238 |
-- fields from <xsl:value-of select="name"/> |
120 |
gerard.lemson |
219 |
<xsl:apply-templates select="attribute" /> |
121 |
|
|
<xsl:apply-templates select="reference" /> |
122 |
|
|
<xsl:apply-templates select="/model//objectType[extends/datatype/@xmiidref = $xmiid]" mode="hierarchy"/> |
123 |
|
|
</xsl:template> |
124 |
gerard.lemson |
148 |
|
125 |
|
|
|
126 |
|
|
|
127 |
bourges.laurent |
238 |
|
128 |
gerard.lemson |
246 |
<xsl:template match="objectType" mode="joined"> |
129 |
bourges.laurent |
238 |
<!-- generate a single table for the whole object hierarchy below the matched objectType --> |
130 |
gerard.lemson |
234 |
<xsl:variable name="tableName"> |
131 |
|
|
<xsl:apply-templates select="." mode="tableName"/> |
132 |
|
|
</xsl:variable> |
133 |
gerard.lemson |
232 |
<xsl:variable name="containers"> |
134 |
gerard.lemson |
229 |
</xsl:variable> |
135 |
bourges.laurent |
251 |
CREATE TABLE <xsl:value-of select="$tableName"/> ( |
136 |
bourges.laurent |
238 |
id bigint not null |
137 |
|
|
<xsl:apply-templates select="." mode="container"/> |
138 |
|
|
<xsl:apply-templates select="attribute" /> |
139 |
|
|
<xsl:apply-templates select="reference" />);&cr;&cr; |
140 |
gerard.lemson |
148 |
</xsl:template> |
141 |
|
|
|
142 |
|
|
|
143 |
|
|
|
144 |
gerard.lemson |
229 |
|
145 |
gerard.lemson |
232 |
<xsl:template match="objectType" mode="container"> |
146 |
|
|
<xsl:variable name="xmiid" select="@xmiid"/> |
147 |
|
|
<xsl:if test="/model//objectType[collection/datatype/@xmiidref = $xmiid]">, containerId bigint not null -- <xsl:value-of select="/model//objectType[collection/datatype/@xmiidref = $xmiid]/name"/>&cr; |
148 |
|
|
</xsl:if> |
149 |
gerard.lemson |
229 |
</xsl:template> |
150 |
gerard.lemson |
232 |
|
151 |
bourges.laurent |
238 |
|
152 |
|
|
|
153 |
|
|
|
154 |
gerard.lemson |
232 |
<xsl:template match="attribute" > |
155 |
|
|
<xsl:param name="prefix"/> |
156 |
|
|
|
157 |
|
|
<xsl:variable name="columnname"> |
158 |
|
|
<xsl:choose> |
159 |
|
|
<xsl:when test="$prefix"> |
160 |
|
|
<xsl:value-of select="concat($prefix,'_',name)"/> |
161 |
|
|
</xsl:when> |
162 |
|
|
<xsl:otherwise> |
163 |
|
|
<xsl:value-of select="name"/> |
164 |
|
|
</xsl:otherwise> |
165 |
|
|
</xsl:choose> |
166 |
|
|
</xsl:variable> |
167 |
|
|
|
168 |
|
|
<xsl:choose> |
169 |
|
|
<xsl:when test="datatype/@class"><xsl:apply-templates select="key('element',datatype/@xmiidref)" mode="columns"><xsl:with-param name="prefix" select="$columnname"/></xsl:apply-templates></xsl:when> |
170 |
bourges.laurent |
238 |
|
171 |
gerard.lemson |
232 |
<xsl:otherwise> |
172 |
|
|
<xsl:variable name="sqltype"> |
173 |
|
|
<xsl:call-template name="sqltype"> |
174 |
|
|
<xsl:with-param name="type" select="datatype/@type"/> |
175 |
|
|
<xsl:with-param name="constraints" select="constraints"/> |
176 |
|
|
</xsl:call-template> |
177 |
|
|
</xsl:variable>, <xsl:value-of select="$columnname"/>&bl;<xsl:value-of select="$sqltype"/><xsl:if test="multiplicity = '1'"> not null</xsl:if>&cr; |
178 |
|
|
</xsl:otherwise> |
179 |
|
|
</xsl:choose> |
180 |
|
|
|
181 |
|
|
</xsl:template> |
182 |
|
|
|
183 |
|
|
|
184 |
|
|
|
185 |
gerard.lemson |
229 |
|
186 |
gerard.lemson |
219 |
<!-- We need lengths for (var)char datatypes --> |
187 |
gerard.lemson |
232 |
<xsl:template name="sqltype"> |
188 |
|
|
<xsl:param name="type"/> |
189 |
gerard.lemson |
230 |
<xsl:param name="constraints"/> |
190 |
bourges.laurent |
238 |
|
191 |
gerard.lemson |
219 |
<xsl:choose> |
192 |
gerard.lemson |
232 |
<xsl:when test="$type = 'boolean'">bit</xsl:when> |
193 |
|
|
<xsl:when test="$type = 'integer'">integer</xsl:when> |
194 |
|
|
<xsl:when test="$type = 'long'">bigint</xsl:when> |
195 |
|
|
<xsl:when test="$type = 'datetime'">dateTime</xsl:when> |
196 |
|
|
<xsl:when test="$type = 'real'">float</xsl:when> |
197 |
|
|
<xsl:when test="$type = 'double'">real</xsl:when> |
198 |
gerard.lemson |
219 |
<xsl:otherwise> |
199 |
|
|
<xsl:variable name="length"> |
200 |
|
|
<xsl:choose> |
201 |
gerard.lemson |
230 |
<xsl:when test="$constraints/length"> |
202 |
|
|
<xsl:value-of select="$constraints/length"/> |
203 |
gerard.lemson |
219 |
</xsl:when> |
204 |
gerard.lemson |
230 |
<xsl:when test="$constraints/maxLength"> |
205 |
|
|
<xsl:value-of select="$constraints/maxLength"/> |
206 |
|
|
</xsl:when> |
207 |
gerard.lemson |
219 |
<xsl:otherwise> |
208 |
|
|
<xsl:value-of select="$defaultVarcharLength"/> |
209 |
|
|
</xsl:otherwise> |
210 |
|
|
</xsl:choose> |
211 |
gerard.lemson |
230 |
</xsl:variable> |
212 |
|
|
<xsl:choose> |
213 |
|
|
<xsl:when test="$length <= 0"><xsl:value-of select="$longstringtype"/></xsl:when> |
214 |
|
|
<xsl:otherwise>varchar(<xsl:value-of select="$length"/>)</xsl:otherwise> |
215 |
bourges.laurent |
238 |
</xsl:choose></xsl:otherwise> |
216 |
gerard.lemson |
219 |
</xsl:choose> |
217 |
gerard.lemson |
148 |
</xsl:template> |
218 |
|
|
|
219 |
bourges.laurent |
238 |
|
220 |
|
|
|
221 |
|
|
|
222 |
gerard.lemson |
232 |
<!-- We need lengths for (var)char datatypes --> |
223 |
|
|
<xsl:template match="*/dataType" mode="columns"> |
224 |
|
|
<xsl:param name="prefix"/> |
225 |
|
|
<xsl:choose> |
226 |
|
|
<xsl:when test="not(attribute)">, <xsl:value-of select="$prefix"/> varchar(256) -- <xsl:value-of select="name"/>&cr;</xsl:when> |
227 |
|
|
<xsl:otherwise><xsl:apply-templates select="attribute"><xsl:with-param name="prefix" select="$prefix"/></xsl:apply-templates></xsl:otherwise> |
228 |
|
|
</xsl:choose> |
229 |
|
|
</xsl:template> |
230 |
bourges.laurent |
238 |
|
231 |
|
|
|
232 |
gerard.lemson |
232 |
|
233 |
bourges.laurent |
238 |
|
234 |
gerard.lemson |
232 |
<!-- We need lengths for (var)char datatypes --> |
235 |
|
|
<xsl:template match="*/enumeration" mode="columns"> |
236 |
|
|
<xsl:param name="prefix"/> |
237 |
bourges.laurent |
238 |
, <xsl:value-of select="$prefix"/> varchar(256) -- <xsl:value-of select="name"/>&cr; |
238 |
gerard.lemson |
232 |
</xsl:template> |
239 |
gerard.lemson |
148 |
|
240 |
|
|
|
241 |
gerard.lemson |
232 |
|
242 |
|
|
|
243 |
gerard.lemson |
219 |
<xsl:template match="reference"> |
244 |
bourges.laurent |
238 |
<xsl:if test="not(subsets)">, <xsl:value-of select="name"/>Id&bl;bigint <xsl:call-template name="nullity"><xsl:with-param name="multiplicity" select="multiplicity"/></xsl:call-template>-- <xsl:value-of select="datatype/@class"/>&cr; |
245 |
|
|
</xsl:if> |
246 |
gerard.lemson |
148 |
</xsl:template> |
247 |
|
|
|
248 |
bourges.laurent |
238 |
|
249 |
|
|
|
250 |
|
|
|
251 |
gerard.lemson |
233 |
<xsl:template name="nullity"> |
252 |
|
|
<xsl:param name="multiplicity"/> |
253 |
|
|
<xsl:choose> |
254 |
|
|
<xsl:when test="$multiplicity = '1' or $multiplicity = '1..*'">not null</xsl:when> |
255 |
|
|
<xsl:otherwise>null</xsl:otherwise> |
256 |
|
|
</xsl:choose> |
257 |
|
|
</xsl:template> |
258 |
gerard.lemson |
229 |
|
259 |
bourges.laurent |
238 |
|
260 |
|
|
|
261 |
|
|
|
262 |
gerard.lemson |
233 |
<xsl:template name="combineNullity"> |
263 |
|
|
<xsl:param name="first"/> |
264 |
|
|
<xsl:param name="second"/> |
265 |
|
|
<xsl:choose> |
266 |
|
|
<xsl:when test="$first = 'not null' and $second = 'not null'"><xsl:value-of select="'not null'"/></xsl:when> |
267 |
|
|
<xsl:otherwise><xsl:value-of select="'null'"/></xsl:otherwise> |
268 |
|
|
</xsl:choose> |
269 |
|
|
</xsl:template> |
270 |
|
|
|
271 |
|
|
|
272 |
|
|
|
273 |
|
|
|
274 |
gerard.lemson |
219 |
<!-- TODO |
275 |
|
|
Add templates retrieving for a given objectType the table it is in |
276 |
|
|
for a given attribute the column(s) it is in |
277 |
|
|
for a given reference the column it is in |
278 |
|
|
for a given collection the containerId column it is in. |
279 |
|
|
--> |
280 |
gerard.lemson |
148 |
|
281 |
gerard.lemson |
234 |
<!-- for now no special camelcase 2 '_' transformation --> |
282 |
bourges.laurent |
238 |
<xsl:template match="objectType" mode="tableName"> |
283 |
gerard.lemson |
234 |
<xsl:value-of select="name"/> |
284 |
bourges.laurent |
238 |
</xsl:template> |
285 |
gerard.lemson |
148 |
|
286 |
gerard.lemson |
234 |
|
287 |
gerard.lemson |
148 |
</xsl:stylesheet> |